Servlet檔案上傳(壓縮檔案、圖片等)
上傳檔案是指把客戶端的檔案傳送到伺服器端,當客戶端向伺服器上傳檔案時,客戶端傳送的HTTP請求正文采用“multipart/form-data”資料型別,它表示複雜的包含多個子部分的複合表單。比如,如下HTML程式碼中,就包含了普通的文字輸入框和兩個用於指定上傳檔案的檔案域。
<form action="UploadImg" method="post" enctype="multipart/form-data"> 測試引數1:<input type="text" name="TextItem"> 上傳檔案1:<input type="file" name="fileItem1"> 上傳檔案2:<input type="file" name="fileItem2"> 上傳檔案3:<input type="file" name="fileItem3"> <input type="submit" value="提交"> </form>
當請求正文為"multipart/form-data"資料型別時,Servlet直接從HttpServletRequest物件中解析複合表單的每個字部份仍然是一項非常複雜的工作。為了簡化對"multipart/form-data"型別資料的處理過程,Apache提供了兩個軟體包來實現檔案的上傳:
(1)、fileupload軟體包(commons-fileupload-版本號.jar):負責上傳檔案的軟體包。
(2)、io軟體包(commons-io-版本號.jar):負責輸入和輸出的軟體包。
這兩個jar包都可以在Apache的官網中下載,網址分別是http://commons.apache.org/fileupload/ 和 http://commons.apache.org/io/ ,Servlet主要利用fileupload軟體包的介面和類來實現檔案的上傳,而fileuoload軟體本身依賴io軟體包,所以兩者缺一不可。
對於一個正文部分為“multipart/form-data”型別的Http請求,fileupload軟體包把請求正文包含的複合表單中的每個子部分看作是一個FileItem物件,FileItem物件分為兩類。
(1)、formFieId:普通表單域型別,表單中的文字框、單選、複選及提交按鈕等常見表單元素
(2)、非formFieId:上傳檔案型別,表單中的檔案域就是這種型別。
FileItemFactory是建立FileItem物件的工廠,DiskFileItemFactory類和DiskFileItem類分別實現了FileItemFactory介面和FileItem介面。DiskFileItemFactory是建立DiskFileItem物件的工廠,而DiskFileItem類表示基於硬碟的FileItem,它能夠把客戶端上傳的檔案資料儲存到硬碟上。
(1)、以下程式程式碼建立了一個DiskFileItemFactory物件,然後設定了在向硬碟寫資料時所用的緩衝區大小,以及所使用的零食目錄。(fileuoload軟體包自身實現中,為了提高向硬碟寫資料的效率,尤其是寫大容量資料的效率,fileuoload軟體包在寫資料時會使用快取,以及向臨時目錄存放一些臨時資料,當然這不一定需要開發人員去設定)
//常見一個基於硬碟的FileItem工廠
DiskFileItemFactory factory = new DiskFileItemFactory();
//設定向硬碟寫資料時所用的緩衝區大小,此處為4M
factory.setSizeThreshold(4*1024*1024);
//設定臨時目錄
factory.setRepository(new File(tempFilePath));
(2)、ServletFileUpload類為檔案的上傳處理器,它與FileItemFactory關聯。以下程式程式碼建立了一個ServletFileUpload物件,它與一個DiskFileItemFactory物件關聯。該類存在setSizeMax()方法用來設定上傳檔案的最大尺寸。
//建立一個檔案上傳處理器
ServletFileUpload upload = new ServletFileUpload(factory);
//設定上傳檔案的最大尺寸,此處為4M
upload.setSizeMax(4*1024*1024);
(3)、建立好了檔案處理器之後,ServletFileUpload提供了parseRequest(HttpServletRequest request)方法來解析HttpServletRequest物件中的複合表單資料,它返回包含一組FileItem物件的List集合。程式碼如下:
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//常見一個基於硬碟的FileItem工廠
DiskFileItemFactory factory = new DiskFileItemFactory();
//建立一個檔案上傳處理器
ServletFileUpload upload = new ServletFileUpload(factory);
//解析複合表單資料,將結果儲存到List物件中
List items = upload.parseRequest(request);
}
(4)、在得到了包含FileItem物件的List集合後,就可以遍歷這個集合,判斷每個FileItem物件的型別,然後做出相應的處理。
Iterator iter = items.iterator();
while(iter.hasNext()){
FileItem item = (FileItem)iter.next();
//判斷FileItem型別
if(item.isFormFileId()){ //處理普通的表單域
//獲取引數名
String name = item.getFieIdName();
//獲取引數值
String value = item.getString();
}else{ //處理檔案型別
//注意:不同的瀏覽器提交的檔名是不一樣的,有些瀏覽器提交上來的檔名是帶有路徑的
String filename = item.getName();
//處理獲取到的上傳檔案的檔名的路徑部分,只保留檔名部分,所以從最後一個\符號的下一個字元開始擷取字串。
filename = filename.substring(filename.lastIndexOf("\\")+1);
//獲取item中的上傳檔案的輸入流
InputStream in = item.getInputStream();
//建立一個檔案輸出流
FileOutputStream out = new FileOutputStream(savePath + "\\" + filename);
//建立一個緩衝區
byte buffer[] = new byte[1024];
//判斷輸入流中的資料是否已經讀完的標識
int len = 0;
//迴圈將輸入流讀入到緩衝區當中,(len=in.read(buffer))>0就表示in裡面還有資料
while((len=in.read(buffer))>0){
//使用FileOutputStream輸出流將緩衝區的資料寫入到指定的目錄(savePath + "\\" + filename)當中
out.write(buffer, 0, len);
}
//關閉輸入流
in.close();
//關閉輸出流
out.close();
//刪除處理檔案上傳時生成的臨時檔案
item.delete();
}
}
做完上述的所有程式碼之後,執行伺服器訪問前段頁面,輸入內容、上傳指定檔案
控制檯輸出語句:
指定目錄的檔案內容: