2012-12-06 44 views
1

我已經寫了下面的方法,這是由我的doPost方法調用來解析請求中給出的multipart/form-data。這一切都很好,我只是不明白髮生了什麼。如果有人能夠在我的嘗試中分解三條線,我會非常感激。我已經閱讀了Apache Commons File Upload documentation,但它對我來說沒有意義,我討厭編寫我不完全理解的代碼。特別是,我想知道在創建工廠和上傳對象時實際發生了什麼。瞭解工作文件上傳解決方案

public static List<FileItem> parseFormRequest(HttpServletRequest request) 
{ 
    List<FileItem> items = null; 

    try 
    { 
     DiskFileItemFactory factory = new DiskFileItemFactory(); 
     ServletFileUpload upload = new ServletFileUpload(factory); 
     items = upload.parseRequest(request); 
    } 
    catch (FileUploadException error) 
    { 
     System.out.println("UploadFileServlet - Error With File Parsing - " + error.getMessage()); 
    } 

    return items; 
} 

BONUS幫助!

我還收到upload.parseRequest(request)的警告,說Type safety: The expression of type List needs unchecked conversion to conform to List<FileItem>。如果任何人都可以解釋這一點,這將真正幫助我得到我所做的。由於

enter image description here

回答

2

工廠只是一個幫手,我稍後會解釋。主要工作由ServletFileUpload完成。

ServletFileUpload將掃描所有上傳的文件(使用解析MIME內容並知道如何處理邊界標記,內容長度等的Iterator)。

對於每個上傳的文件,解析方法詢問FileItemFactory創建本地表示用於上載的文件,然後拷貝從存儲器(例如,從HTTP POST請求,其被保存在內存中)的內容上的實際文件磁盤。

簡化,程序如下:

  • 獲取下一個上傳的文件
  • 向工廠本地文件(「的FileItem」)
  • 從內存(從HttpServletRequest中)將內容複製到本地文件(一個java.io.文件中的一個DiskFileItemFactory的情況下)
  • 環路達到

直到HTTP請求的結束請參見下面的類的源的信息

  • org.apache.commons.fileupload.FileUploadBase.parseRequest (的RequestContext)
  • org.apache.commons.fileupload.FileUploadBase.FileItemIteratorImpl.FileItemStreamImpl

這設計允許切換到另一個文件存儲設施,例如: 您可以用您自己的DatabaseFileItemFactory替換DiskFileItemFactory,以便上載的文件存儲在數據庫中而不是服務器上的本地文件中。代碼更改只會影響單行,其餘的commons-fileupload可以原樣使用(例如解析HTTP請求,遍歷上傳的文件等)。

對於第二個問題: commons-fileupload似乎是Java 1.4兼容的,所以parseRequest() 的返回類型實際上是一個非類型的java.util.List - 它缺少聲明列表只包含FileItem對象(例如java.util.List<FileItem>)。 由於您聲明變量items的類型爲List<FileItem>,因此Java編譯器會警告您這種不匹配。

在這種情況下,你正確地做到了,你可以通過添加忽略警告如下:

@SuppressWarnings("unchecked") 
public static List<FileItem> parseFormRequest(HttpServletRequest request) 
{ 
    ... 
+0

+1,因爲我差不多寫完一個類似的回覆,但你的措辭更好。 DatabaseFileItemFactory理念適用於未來請求可能需要訪問上載數據的集羣環境。在臨時本地文件僅在接收到原始請求的節點上可用的情況下,數據庫條目的密鑰可以存儲在會話中,並且便宜地複製到其他節點以更好地進行故障轉移處理。 – GargantuChet

+0

我對DiskFileItemFactory感到困惑。這是如何寫入一個文件,以及它在哪裏寫信,因爲我沒有澄清一個位置。它只是寫入一個文件,然後立即刪除它? – gmustudent

+0

「DiskFileItemFactory將內容保存在內存中,對於較小的項目或在磁盤上的臨時文件中,用於較大的項目。大小閾值(高於該閾值的內容將存儲在磁盤上)是可配置的,因爲臨時文件將被創建。「您需要使用FileItem.write(yourFile)將上傳的文件保存到未自動清理的地方。 – mhaller

0

你需要花一些時間在documentation

從我可以收集的內容中,ServletFileUpload實例使用您提供的工廠實際創建請求中的文件實例。您使用了將文件寫入磁盤的工廠;還有其他選項(例如內存)。通過指定工廠,您可以指定創建的文件的類型。

當你調用

upload.parseRequest(request)

ServletFileUpload實例會突破請求數據和實際創建它找到的文件,使用的工廠,並將其返回到您在列表中。

如果你看看parseRequestdocumentation你會注意到該方法只返回List。在您的代碼中,您將該返回列表分配給List<FileItem>。這需要一個強制轉換,這就是爲什麼你得到編譯器警告。

+0

我不明白爲什麼,如果我分配列表到列表 – gmustudent

+0

你是一個列表分配列表''我會得到一個警告 – hvgotcodes

+0

所以我需要做一個(名單)鑄 – gmustudent

-1

我需要用於調用該函數的Java代碼... 我需要這個Servlet用來參數添加到HttpServletRequest的代碼