2008-12-22 59 views
4

我在写一个让用户上传图片的简单应用程序。上传后,用户可以标记它们或将其删除。Java/JSP图像上传。在哪里保存这些图像文件?

我想出了如何上传文件并在文件上传后保存文件。我正在跟踪保存图像的全球路径。在数据库中,我保留关于类似的文件名,标签等

图像我使用的Java/JSP的元数据(特别是条纹框架,但我的问题是通用的)。

我的问题是,我上传这些图像文件的位置在哪里?

现在我有两个Web应用程序部署在Tomcat服务器上。一个主要的Web应用程序和另一个是我上传图像的位置。

但是这不起作用,因为我在主应用程序中看不到上传的图像,直到重新部署/重新启动Tomcat。

这似乎像Tomcat不会自动选择新上传的图像。

有没有人有任何解决方案?

这是一个简单的项目,所以我不想将它们存储在数据库中或使用Apache进行图像处理。这对于这个小项目来说太复杂了。

谢谢。

+0

我不是个人冒犯,但那个标题有点粗俗,你不觉得吗?你如何编辑它有点礼貌。 – 2008-12-22 02:26:08

回答

5

绝对不会将图像存储在数据库中,但您希望将图像路径存储在数据库中。这将允许您在任何地方存储图像。

由于使用两个tomcat的应用程序,你最好的选择可能是将图像存储或者应用程序之外,并流中的图像返回给用户,而不是让tomcat的管理文件。否则,我会问你为什么试图用两个Web应用程序来做到这一点。

0

我正在使用两个Web应用程序来避免在重新部署新的主应用程序战争文件的情况下写入上传的图像。

但正如你所提到的,除了通过Servlet或其他东西流式传输外,没有别的选择,我想我可以将它们放在tomcat目录之外。

我想避免编写这个Streaming Servlet。在编写流式servlet时,处理所有混乱(如适当的内容类型,404等)的项目太小。

3

但是,将上传的图像存储在web-app目录中并不是一件明智的事情,而且您知道这一点。

顺便说一句,你可能想看看这个stackoverflow thread,最近讨论在哪里存储图像。它可能无法解决你的问题,肯定会给你更多的信心,你在做什么。

0
import java.io.BufferedInputStream; 
import java.io.BufferedOutputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.PrintWriter; 

import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

/** 
* Image streaming Servlet. 
*/ 
public class ImageDisplayServlet extends HttpServlet { 
    private static final long serialVersionUID = 1L; 

    /** 
    * @see HttpServlet#HttpServlet() 
    */ 
    public ImageDisplayServlet() { 
     super(); 
    } 

    /** 
    * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) 
    */ 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     String relativePath = trimToEmpty(request.getPathInfo()); 

     // Make sure no one try to screw with us. 
     // This is important as user can literally access any file if we are not careful 
     if(isXSSAttack(relativePath) == false) { 
      String pathToFile = this.getServletContext().getRealPath(request.getPathInfo()); 
      File file = new File(pathToFile); 

      System.out.println("Looking for file " + file.getAbsolutePath()); 

      // show a 404 page 
      if(!file.exists() || !file.isFile()) { 
       httpError(404, response); 
      } else { 
       try { 
        streamImageFile(file, response); 
       } catch(Exception e) { 
        // Tell the user there was some internal server error.\ 
        // 500 - Internal server error. 
        httpError(500, response); 
        e.printStackTrace(); 
       } 
      } 
     } else { 
      // what to do if i think it is a XSS attack ?!? 
     } 
    } 

    private void streamImageFile(File file, HttpServletResponse response) { 
     // find the right MIME type and set it as content type 
     response.setContentType(getContentType(file)); 
     BufferedInputStream bis = null; 
     BufferedOutputStream bos = null; 
     try { 
      response.setContentLength((int) file.length()); 

      // Use Buffered Stream for reading/writing. 
      bis = new BufferedInputStream(new FileInputStream(file)); 
      bos = new BufferedOutputStream(response.getOutputStream()); 

      byte[] buff = new byte[(int) file.length()]; 
      int bytesRead; 

      // Simple read/write loop. 
      while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) { 
       bos.write(buff, 0, bytesRead); 
      } 
     } catch (Exception e) { 

      throw new RuntimeException(e); 
     } finally { 
      if (bis != null) { 
       try { 
        bis.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
        // To late to do anything about it now, we may have already sent some data to user. 
       } 
      } 
      if (bos != null) { 
       try { 
        bos.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
        // To late to do anything about it now, we may have already sent some data to user. 
       } 
      } 
     } 
    } 

    private String getContentType(File file) { 
     if(file.getName().length() > 0) { 
      String[] parts = file.getName().split("\\."); 
      if(parts.length > 0) { 
       // only last part interests me 
       String extention = parts[parts.length - 1]; 
       if(extention.equalsIgnoreCase("jpg")) { 
        return "image/jpg"; 
       } else if(extention.equalsIgnoreCase("gif")) { 
        return "image/gif"; 
       } else if(extention.equalsIgnoreCase("png")) { 
        return "image/png"; 
       } 
      } 
     } 
     throw new RuntimeException("Can not find content type for the file " + file.getAbsolutePath()); 
    } 

    private String trimToEmpty(String pathInfo) { 
     if(pathInfo == null) { 
      return ""; 
     } else { 
      return pathInfo.trim(); 
     } 
    } 

    private void httpError(int statusCode, HttpServletResponse response) { 
     try { 
      response.setStatus(statusCode); 
      response.setContentType("text/html"); 
      PrintWriter writer = response.getWriter(); 
      writer.append("<html><body><h1>Error Code: " + statusCode + "</h1><body></html>"); 
      writer.flush(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    private boolean isXSSAttack(String path) { 
     boolean xss = false; 
     // Split on the bases of know file separator 
     String[] parts = path.split("/|\\\\"); 

     // Now verify that no part contains anything harmful 
     for(String part : parts) { 
      // No double dots .. 
      // No colons : 
      // No semicolons ; 
      if(part.trim().contains("..") || part.trim().contains(":") || part.trim().contains(";")) { 
       // Fire in the hole! 
       xss = true; 
       break; 
      } 
     } 
     return xss; 
    } 

    /** 
    * @see HttpServlet#doPost(Ht/promotions/some.jpgtpServletRequest request, HttpServletResponse response) 
    */ 
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     doGet(request, response); 
    } 
} 

确定这里是一个Servlet,我很快写了可以流图片:

这里是限制的名单,知道问题:

  • 可能有护理XSS漏洞利用
  • 不生产作为参考准备使用
  • 图像需要在web应用程序目录。可以很容易地改变,但我太懒了(这是不值得的项目太小)
  • 只有流jpg,gif或png文件。

用法:

比方说您部署该Web应用程序调用的图像作为单独的应用程序。

http://www.example.com/images/promotions/promo.jpg

意味着应该有一个目录中的“促销”与图像“promo.jpg”与此图片的Web应用程序。

PS:别问我为什么要这么做,吸大的时间Servlet容器唯一的解决办法。

0
<servlet> 
    <description></description> 
    <display-name>ImageDisplayServlet</display-name> 
    <servlet-name>ImageDisplayServlet</servlet-name> 
    <servlet-class>com.example.images.ImageDisplayServlet</servlet-class> 
    </servlet> 
    <servlet-mapping> 
    <servlet-name>ImageDisplayServlet</servlet-name> 
    <url-pattern>/*</url-pattern> 
    </servlet-mapping> 

哦雅配置您的Servlet像上面获得最佳效果:P

2

我以不同的方式解决了这个。

首先,不可移植的方式,是Glassfish的(而且我相信Tomcat的为好),您可以到web应用层次映射的外部目录。这工作得很好,而且完全符合你的要求。它允许您将图像存储在远离Web应用程序的外部目录中,但仍然可以为其提供服务。

但是,这种技术是不便携的。

到我便携做到了该方法是通过创建一个过滤器。

你把过滤器某处明显,说“/图片”。

什么过滤器确实是这样的:

  • 它检查图像(或任何东西,它与任何静态资源工作)在Web应用程序中的一个特殊的目录。对于我们的例子,我们将使用url“/ webapp/images”。

  • 如果文件不存在,我们从外部位置的文件复制到Web应用程序中的适当位置。所以,让我们说reqyest url是“/images/banner.gif”。而且你的文件存储在“/ home/app/images”的磁盘上。所以,我们的源文件是“/home/app/images/banner.gif”。然后,我们将它复制到我们想要它在webapp树中的位置。我们为此使用“ServletContext.getRealPath”。因此,目标将是“ServletContext.get RealPath(”/ webapp/images/banner.gif“)。只需将源复制到目标。

  • 如果文件已经存在或现在存在,只需转发到/webapp/images/banner.gif上的实际图像即可。

实际上,您最终会在您的webapps部署树中拥有文件缓存。不利的一面是它是一个缓存,所以需要维护它(也就是说,您应该检查原始文件是否比缓存更新,确保删除源文件时是否删除等)。此外,它会复制您的资源,因此您的映像最终会消耗两倍的磁盘空间。最后,启动时会有最初的复制成本。

但是,它工作,它可以防止你必须使用自己的代码提供静态资源。 (这是第三种解决方案,将一个过滤器/ servlet映射为拦截URL并简单地将它自己流。)

我会看看Tomcat中的构造(假设它存在)为您执行映射。我知道它存在于Glassfish中。 (谷歌改变了Glassfish的看法,看看它是如何工作的。)