1. 程式人生 > >Servlet檔案上傳(壓縮檔案、圖片等)

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();
    }
}

做完上述的所有程式碼之後,執行伺服器訪問前段頁面,輸入內容、上傳指定檔案

控制檯輸出語句:

指定目錄的檔案內容: