Struts FileUpload 異常處理之Processing of multipart/form-data request failed.

問題:
在使用FileUpload的過程當中,有一個常常拋出異常以下:
ERROR [http-8081-Processor21] (CommonsMultipartRequestHandler.java:201) -2008-04-10 11:20:27,671 Failed to parse multipart request
org.apache.commons.fileupload.FileUploadException: Processing of multipart/form-data request failed. temp\upload__3d7cf8b_11936276cf8__7ffd_00000011.tmp (系統找不到指定的路徑。)
    at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:384)
    at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:268)
    at org.apache.struts.upload.CommonsMultipartRequestHandler.handleRequest(CommonsMultipartRequestHandler.java:193)
    at org.apache.struts.util.RequestUtils.populate(RequestUtils.java:443)
    at org.apache.struts.action.RequestProcessor.processPopulate(RequestProcessor.java:804)
    at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:203)
    at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196)
    at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
問題分析:
在我使用Struts FileUpload時有如下幾個關鍵部分:
  • 定義Form的Enctype屬性multipart/form-data,添加<input type=file>的域;
  • 在FormBean中定義與file域名稱相同、類型爲FormFile的屬性;
  • 在strut-config.xml定義或修改controller標記,分別設置maxFileSize=10M、bufferSize=409六、tempDir=temp、inputForward=true等屬性;
  • 得到FormFile類型的屬性,將字節流寫入指定的文件中。
而在不超出maxFileSize的範圍中有一些較大文件都不能上傳成功,並拋出上述異常,在指定的tempDir目錄中也不能找到相應的tmp文件。在已知的單獨使用commons-fileupload時常常使用的handler是ServletFileUpload或DiskFileUpload,而在查到的資料中的解釋是使用DiskFileUpload就能夠解決上面的問題,那麼StrutsFileUpload是怎麼使用這些類來處理上傳的呢?查看struts-config_1_2.dtd有一個屬性是multipartClass是用來設置處理這種請求的類,默認值是CommonsMultipartRequestHandler,那麼應該有其它不一樣的處理類,因而在"org.apache.struts.upload中找到類DiskMultipartRequestHandler。這個類的處理方式是直接在臨時文件目錄寫臨時文件。那麼定義multipartClass=org.apache.struts.upload.DiskMultipartRequestHandler,則異常再也不出現。
可是javadoc中明明白白的寫的是在commons-fileupload之後的版本中DiskMultipartRequestHandler類將由CommonsMultipartRequestHandler替代,使用CommonsMultipartRequestHandler纔是明智的選擇。那麼分析一下,發現後者可用的緣由就應該在於後者是使用硬盤空間做爲交換空間,則前者就應當是使用內存作爲交換空間的,那麼使用內存空間應該是有邊界限制的,這個屬性就是memFileSize,其默認值是256K,在上傳拋出異常時使用的文件就是大於這個數字的文件,發現它對應的其實就是DiskFileItemFactory的sizeThreshold屬性。而對memFileSize的解釋就是上傳時能夠在內存中保留的文件的最大值,超出這個數字則保存在其它的介質中如硬盤。也就是說要正常使用CommonsMultipartRequestHandler類處理上傳請求,能夠將memFileSize定義到與maxFileSize同樣大,但顯而易見的是一旦有更大的上傳文件需求時,就會從新遇到問題,如此大的內存開銷是顯然是不合理的。
按道理來說,CommonsMultipartRequestHandler作爲multipartClass默認值和下一版本的保留類,應該是能夠正確的使用配置文件中定義的memFileSize屬性的,那麼既然在異常中有「系統找不到指定的路徑」字樣,那就從文件系統的路徑來試着解決問題。tempDir指定的目錄是temp,異常的提示應該就是找不到這個目錄,從本機應用中來看這個temp就是tomcat根目錄下的temp,但就是這個目錄在我本機上是能夠找到的,在服務器上卻老是提示異常。查看struts-config_1_2.dtd,對於這個參數的解釋是「指定文件上傳時的臨時工做目錄.若是沒有設置,將才用Servlet容器爲web應用分配的臨時工做目錄」。那麼在個人應用中若是不指定tempDir,這個目錄就是%TOMCAT_HOME%\temp;若是指定的話,就要指定絕對路徑,如「C:\\temp」。
解決方法:
一、指定multipartClass爲org.apache.struts.upload.DiskMultipartRequestHandler,不推薦使用這種方式;
二、指定memFileSize與maxFileSize相同的值,用於上傳文件較小的狀況,這種方式其實也是一種錯誤的方式,不推薦;
三、指定tempDir爲絕對目錄;
四、若是應用服務器能夠爲應用分配臨時目錄的話,能夠不指定tempDir;
五、即使tempDir指定的是相對目錄,如tempDir="temp",也並非錯誤的,它應該是存在於固然應用的一個相對目錄。
補充:
tempDir指定的目錄中可能會隨着時間推移出現不少後綴爲"tmp"的垃圾文件,commons-fileupload提供了一個不錯的解決方法,就是把下面的代碼加入到web.xml中便可。
<listener>
        <listener-class>
          org.apache.commons.fileupload.servlet.FileCleanerCleanup
        </listener-class>
</listener>
須要注意的是FileCleanerCleanup是commons-fileupload1.2之後的版本纔有的類。
 
______________________________________________________
 
 
看完以上, 修改struts.xml文件
Xml代碼 複製代碼
  1. <!-- 臨時文件存放路徑 -->  
  2.     <constant name="struts.multipart.saveDir" value="D://chain/jboss-web/MyTemp/"></constant>  
有待測試驗證.
相關文章
相關標籤/搜索