陳濤++黃艷峰
摘要:文件上傳是Web開發(fā)中經(jīng)常需要實(shí)現(xiàn)的功能,介紹了Java Web開發(fā)中主流的文件上傳方法,包括SmartUpload和Commons FileUpload兩種組件上傳,以及Servlet 3.0支持的原生API文件上傳。給出了三種方法實(shí)現(xiàn)文件上傳的主要代碼,并對(duì)三者在上傳大文件時(shí)的效率進(jìn)行了比較。
關(guān)鍵詞:SmartUpload;Commons FileUpload;Servlet 3.0;文件上傳;Java Web
中圖分類號(hào):TP311 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1009-3044(2016)11-0048-02
在Web應(yīng)用開發(fā)中,文件上傳是經(jīng)常需要實(shí)現(xiàn)的功能,目前廣為流傳的方法是使用第三方的文件上傳組件。具體在Java web開發(fā)領(lǐng)域,常用的上傳組件有SmartUpload、Apache Commons FileUpload等。在最新的Servlet 3.0規(guī)范中,對(duì)文件上傳提供了API的原生支持,這樣就可以不再依賴任何第三方上傳組件。本文將舉例探討以上三種文件上傳方法的特點(diǎn),最后從上傳效率上給出三種方法的比較。
1 SmartUpload組件
SmartUpload是在Java Web開發(fā)中使用較多的一個(gè)文件上傳下載組件,它的特點(diǎn)是使用非常簡單,只需幾行代碼即可實(shí)現(xiàn)文件的上傳下載,所以即使SmartUpload已經(jīng)停止了更新,但直到今天依然是很多開發(fā)者的選擇。
SmartUpload的API中主要包括SmartUpload、Files、File、Request等核心類。由于篇幅限制,本文就不再列出各個(gè)類的方法了,讀者可自行上網(wǎng)查閱。下面舉例說明該組件的使用方法。
1) 編寫文件上傳表單文件
文件上傳表單使用屬性值為file的input標(biāo)記,注意表單必須以post方式提交,表單的enctype屬性必須是multipart/form-data。該文件在三種文件上傳方法中都需要用到。
2) 編寫JSP文件實(shí)現(xiàn)文件上傳
首先需要將下載的SmartUpload組件jar包拷貝至Web應(yīng)用的WEB-INF\lib目錄下,然后編寫實(shí)現(xiàn)文件上傳功能的JSP文件。文件上傳核心代碼如下:
注意不同瀏覽器的默認(rèn)設(shè)置不同,IE瀏覽器默認(rèn)提交文件的整個(gè)路徑(可以在Internet安全設(shè)置更改為不包含本地路徑),而火狐或谷歌瀏覽器默認(rèn)只提交文件名,所以需要考慮可能包含路徑的情況,把文件名從中提取出來。Commons FileUpload組件自身沒有提供限制上傳文件類型的方法,需要自行編碼從文件名取出擴(kuò)展名并與允許上傳的文件擴(kuò)展名進(jìn)行比較,然后給出用戶相應(yīng)的錯(cuò)誤提示。除了使用FileItem的write()方法保存文件外,還可以通過FileItem的getInputStream()方法獲取文件輸入流,然后再通過輸出流保存至文件甚至是數(shù)據(jù)庫。在上傳文件時(shí)如果超出了文件大小限制,系統(tǒng)會(huì)拋出異常FileSizeLimitExceedException,此異常是FileUploadException異常的子類,所以可以捕獲該異常,并在異常處理代碼中給出用戶錯(cuò)誤提示。
3 Servlet 3.0文件上傳
上述兩種文件上傳方法都需要用到第三方組件,而在最新的Servlet 3.0規(guī)范中,提供了對(duì)文件上傳的原生支持,直接使用Servlet 3.0提供的API就能夠輕松實(shí)現(xiàn)文件上傳。較之Servlet2.5主要是增加了兩個(gè)類:MultipartConfig和Part。其中MultipartConfig是注解類,要想讓Servlet支持文件上傳只需在其前面添加如下形式注解即可:
@MultipartConfig(maxFileSize=1024*1024*300) //設(shè)置單個(gè)文件最大上傳大小,如300M
另外HttpServletRequest類還增加了一個(gè)getParts()方法,該方法可以獲取表單提交過來的所有上傳文件,這些文件信息封裝在一個(gè)個(gè)的Part對(duì)象中。Part類提供了write方法用于保存上傳的文件。在Servlet的doPost()方法編寫如下代碼:
for(Part part : request.getParts()) { //遍歷所有上傳的文件
String filename = getFilename(part); //自定義方法從請(qǐng)求頭信息中得到文件名
File savePath = request.getServletContext().getRealPath(“upload\\”) + filename;
part.write(savePath); //保存上傳的文件到指定的路徑
}
因?yàn)镾ervlet 3.0沒有提供直接獲取文件名的方法,所以只能自行編寫方法getFilename()從請(qǐng)求頭中解析文件名。以火狐瀏覽器為例(若是IE,則文件名帶路徑),請(qǐng)求頭格式為:
Content-Disposition: form-data; name="fileName"; filename="test.avi"。getFilename()方法代碼如下:
private String getFilename(Part part) {
String contentDisp = part.getHeader("content-disposition");
String[] tokens = contentDisp.split(";");
for (String token : tokens) {
if (token.trim().startsWith("filename")) {
String filename = token.substring(token.indexOf("=") + 2, token.length()-1);
return filename.substring(filename.lastIndexOf("\\")+1); //兼容所有瀏覽器
}
}
return "";
}
如果上傳文件違法大小限制,在獲取Part對(duì)象時(shí)將拋出IllegalStateException異常,所以可以將以上for循環(huán)代碼置入try-catch結(jié)構(gòu)中,通過捕獲IllegalStateException異常來判斷文件是否超出大小限制。對(duì)于上傳文件后綴的限制方法與Commons FileUpload組件一樣,也是在得到的文件名中提取擴(kuò)展名,再與允許上傳的文件擴(kuò)展名比較即可。
4 運(yùn)行測(cè)試
分別運(yùn)行以上三種文件上傳程序,當(dāng)上傳體積較小文件時(shí),三者在資源利用率及響應(yīng)時(shí)間方面差別不太顯著,但當(dāng)增加上傳文件大小時(shí),例如上傳300M左右的視頻文件,經(jīng)測(cè)試使用SmartUpload組件、Commons FileUpload組件、Servlet 3.0 API上傳文件花費(fèi)的平均時(shí)間分別為6.642s、5.174s、4.750s。從資源占用情況來看,Servlet 3.0 API文件上傳也是最節(jié)約系統(tǒng)資源的方法。
5 結(jié)論
本文分析對(duì)比了目前Java Web開發(fā)中三種常見的文件上傳方法,前兩種方法需要借助第三方組件來實(shí)現(xiàn),其中SmartUpload組件代碼簡單,實(shí)現(xiàn)方便,但目前已停止更新,并且在上傳大文件時(shí)效率不高,而Commons FileUpload組件目前依然在更新維護(hù)中,上傳大文件時(shí)有不錯(cuò)的性能,并且也被很多主流框架所使用。最后一種文件上傳方法使用Servlet 3.0自身的API來實(shí)現(xiàn),不再依賴第三方組件,上傳效率比Commons FileUpload也更為高效,所以如果Java Web項(xiàng)目是基于Java EE 6以上版本開發(fā)的,建議考慮使用Servlet 3.0 API的文件上傳方法。
參考文獻(xiàn):
[1] 張書鋒.基于Java語言的文件上傳組件研究[J].電腦知識(shí)與技術(shù),2013(33).
[2] 劉楊. JSP項(xiàng)目開發(fā)常用文件上傳組件比較及舉例[J].電腦編程技巧及維護(hù),2015(8).
[3] 周兵.基于JSP文件上傳中的問題探討及改進(jìn)方案[J].蘭州工業(yè)學(xué)院學(xué)報(bào),2015(4).