2008-12-22 62 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的看法,看看它是如何工作的。)