Commons是Apache開放原始碼組織中的一個Java子項目,該項目主要涉及一些開 發中常用的模組,例如檔案上傳、命令列處理、資料庫連接池、XML設定檔處理等。這些項目集合了來自世界各地軟體工程師的心血,其效能、穩定性等方面都 經受得住實際應用的考驗。有效地利用這些項目將會給開發帶來顯而易見的效果。Fileupload就是其中用來處理HTTP檔案上傳的子項目。本文主要介 紹如何使用Fileupload來處理瀏覽器提交到伺服器的檔案資訊。
為了讓首次接觸Fileupload的開發人員能夠更直觀的理解該項目,我們將實現一個簡單的檔案上傳功能,並一步步介紹開發步驟,以及詳細的代碼。
環境準備
1. 下載並安裝Tomcat(已經有很多關於Tomcat安裝以及使用的文章,在這裡不再介紹);
2. 下載File upload的jar包commons-fileupload-1.0-beta-1.jar,並將該檔案拷貝到{$TOMCAT}/common/lib目錄下(其中{$TOMCAT}為Tomcat的安裝目錄);
3. 由於Fileupload子項目同時要用到另外一個項目commons-Beanutils,所以必須下載Beanutils,並將解壓後的檔案commons-beanutils.jar拷貝到{$TOMCAT}/common/lib目錄下。
開發檔案上傳頁面
檔案上傳的介面1所示。為了增加效率我們設計了三個檔案域,同時上傳三個檔案。
圖1 檔案上傳介面
頁面的HTML代碼如下:
<html> <head> <title>檔案上傳示範</title> </head> <body bgcolor=“#FFFFFF”text=“#000000” leftmargin=“0”topmargin=“40”marginwidth=“0” marginheight=“0”> <center> <h1>檔案上傳示範</h1> <form name=“uploadform”method=“POST” action=“save.jsp”ENCTYPE=“multipart/form-data”> <table border=“1”width=“450”cellpadding=“4” cellspacing=“2”bordercolor=“#9BD7FF”> <tr><td width=“100%”colspan=“2”> 檔案1:<input name=“file1”size=“40”type=“file”> </td></tr> <tr><td width=“100%”colspan=“2”> 檔案2:<input name=“file2”size=“40”type=“file”> </td></tr> <tr><td width=“100%”colspan=“2”> 檔案3:<input name=“file3”size=“40”type=“file”> </td></tr> </table> <br/><br/> <table> <tr><td align=“center”><input name=“upload” type=“submit”value=“開始上傳”/></td></tr> </table> </form> </center> </body> </html> |
代碼中要特別注意的是黑體處。必須保證表單的ENCTYPE屬性值為multipart/form-data,這樣瀏覽器才能正確執行上傳檔案的操作。
處理上傳檔案資訊
由於本文主要是講述如何使用Commons-fileupload,所以為了便於修改、調試,上傳檔案的儲存使用一個JSP檔案來進行處理。我們將瀏覽器上傳來的所有檔案儲存在一個指定目錄下並在頁面上顯示所有上傳檔案的詳細資料。儲存頁面處理結果見圖2所示。
圖2 儲存頁面
下面來看看save.jsp的代碼:
<% /** * 示範檔案上傳的處理 * @author <a href=“mailto:winter.lau@163.com”>Winter Lau</a> * @version $Id: save.jsp,v 1.00 2003/03/01 10:10:15 */ %> <%@ page language=“java”contentType=“text/html;charset=GBK”%> <%@ page import=“java.util.*”%> <%@ page import=“org.apache.commons.fileupload.*”%> <html> <head> <title>儲存上傳檔案</title> </head> <% String msg = “”; FileUpload fu = new FileUpload(); // 設定允許使用者上傳檔案大小,單位:位元組 fu.setSizeMax(10000000); // maximum size that will be stored in memory? // 設定最多隻允許在記憶體中儲存的資料,單位:位元組 fu.setSizeThreshold(4096); // 設定一旦檔案大小超過getSizeThreshold()的值時資料存放在硬碟的目錄 fu.setRepositoryPath(“C://TEMP”); //開始讀取上傳資訊 List fileItems = fu.parseRequest(request); %> <body bgcolor=“#FFFFFF”text=“#000000” leftmargin=“0”topmargin=“40”marginwidth=“0” marginheight=“0”> <font size=“6”color=“blue”>檔案清單:</font> <center> <table cellpadding=0 cellspacing=1 border=1 width=“100%”> <tr> <td bgcolor=“#008080”>檔案名稱</td> <td bgcolor=“#008080”>大小</td> </tr> <% // 依次處理每個上傳的檔案 Iterator iter = fileItems.iterator(); while (iter.hasNext()) { FileItem item = (FileItem) iter.next(); //忽略其他不是檔案域的所有表單資訊 if (!item.isFormField()) { String name = item.getName(); long size = item.getSize(); if((name==null||name.equals(“”)) && size==0) continue; %> <tr> <td><%=item.getName()%></td> <td><%=item.getSize()%></td> </tr> <% //儲存上傳的檔案到指定的目錄 name = name.replace(‘:’,‘_’); name = name.replace(‘//’,‘_’); item.write(“F://”+ name); } } %> </table>
<br/><br/> <a href=“upload.html”>返回上傳頁面</a> </center> </body> </html> |
在這個檔案中需要注意的是FileUpload對象的一些參數值的意義,如下面代碼所示的三個參數sizeMax、sizeThreshold、repositoryPath:
FileUpload fu = new FileUpload(); // 設定允許使用者上傳檔案大小,單位:位元組 fu.setSizeMax(10000000); // maximum size that will be stored in memory? // 設定最多隻允許在記憶體中儲存的資料,單位:位元組 fu.setSizeThreshold(4096); // 設定一旦檔案大小超過getSizeThreshold()的值時資料存放在硬碟的目錄 fu.setRepositoryPath(“C://TEMP”); |
這3個參數的意義分別為:
SizeMax 用來設定上傳檔案大小的最大值,一旦使用者上傳的檔案大小超過該值時將會拋出一個FileUploadException異常,提示檔案太大;
SizeThreshold 設定記憶體中緩衝區的大小,一旦檔案的大小超過該值的時候,程式會自動將其它資料存放在repositoryPath指定的目錄下作為緩衝。合理設定該參數的值可以保證伺服器穩定高效的運行;
RepositoryPath 指定緩衝區目錄。
使用注意事項
從實際應用的結果來看該模組能夠穩定高效的工作。其中參數 SizeThreshold的值至關重要,設定太大會佔用過多的記憶體,設定太小會頻繁使用硬碟作為緩衝以致犧牲效能。因此,設定該值時要根據使用者上傳檔案 大小分布情況來設定。例如大部分檔案大小集中在100KB左右,則可以使用100KB作為該參數的值,當然了再大就不合適了。使用commons- fileupload來處理HTTP檔案上傳的功能模組很小,但是值得研究的東西很多。