Servlet實現文件的上傳下載

一、文件上傳入門

1. 應用:

 用戶上傳頭像、上傳圖片、郵件上傳附件等

2. 頁面表單的實現

    文件上傳表單和普通表單有兩個區別

    1) 需要文件上傳字段  <input type=”file” />

    2) form 表單的 enctype 屬性需要指定爲 multipart/form-data

3. 服務器端解析request

    在 Servlet 中通過 request.getInputStream 獲得表單上傳數據,會發現數據是分段發送的

由於自己寫程序解析有難度,我們可以使用Apache 開發的開源組件Commons-fileupload

需要導入 jar 包Commons-fileupload 和Commons-io

4 . UploadServlet 中處理文件上傳程序

 

// 1. 創建工廠類

DiskFileItemFactory factory = new DiskFileItemFactory();

// 2. 創建FileUpload對象

ServletFileUpload upload = new ServletFileUpload(factory);

// 3. 判斷是否是上傳表單

boolean b = upload.isMultipartContent(request);

if(!b) {

    // 不是文件上傳

request.setAttribute("message", "對不起,不是文件上傳表單!");

request.getRequestDispatcher("/message.jsp").forward(request, response);

    return;

}

// 是文件上傳表單

// 4. 解析request,獲得FileItem項

List<FileItem> fileitems = upload.parseRequest(request);

// 5. 遍歷集合

for(FileItem item : fileitems) {

    // 判斷是不是普通字段

if(item.isFormField()) {

    String name = item.getFieldName();

    String value = item.getString();

    // 手工的轉換了

    value = new String(value.getBytes("iso-8859-1"),"utf-8");

    System.out.println(name + "=" + value);

} else {

    // 文件上傳字段

    // 獲得文件名

    String filename = item.getName();

    System.out.println(filename);

    filename = filename.substring(filename.lastIndexOf("\\")+1);

   

    System.out.println(filename);

    // 創建文件

    ServletContext context = getServletContext();

    String dir = context.getRealPath("WEN-INF/upload");

    File file = new File(dir, filename);

    file.createNewFile();

   

    // 獲得流,讀取數據寫入文件

    InputStream in = item.getInputStream();

    FileOutputStream fos = new FileOutputStream(file);

   

    int len;

    byte[] buffer = new byte[1024];

    while((len=in.read(buffer))>0)

       fos.write(buffer,0,len);

    fos.close();

    in.close();

    item.delete();    // 刪除臨時文件

}

 

 

二、 文件上傳處理細節

1. 中文亂碼問題

    1) 文件名中文亂碼問題,解決辦法: 告訴文件上傳組件以什麼編碼方式來解碼文件名

       ServletUpload.setCharacterEncoding(“utf-8”);

       request. setCharacterEncoding(“utf-8”);

    

    2) 普通字段中文亂碼問題

       fileitem.getString(“utf-8”);      

 

2.   臨時文件

    對於大文件不能緩存在內存,需要緩存到硬盤,爲了方便管理,我們需要設置臨時文件存放目錄

    // 設置臨時文件的存放位置

factory.setRepository(new File("d:/temp"));

 

    文件上傳完畢需要刪除臨時文件,否則會導致服務器存在兩份上傳文件

// 注意,需要先將流進行關閉,否則會導致臨時文件無法刪除

out.close();

in.close();

// 刪除臨時文件

fileitem.delete();

 

3. 文件存放目錄

    1) 目錄需要隱藏,禁止外界直接訪問

    2) 文件名需要保證不重複

    3) 文件應該分目錄存放

 

三、上傳進度條

1. 實現進度監聽

    需要實現對文件上傳進度的監聽,需要給FileUpload 對象添加 ProgressListener

    在upload方法中對與進度相關的數據進行處理

    upload.setProgressListener(new ProgressListener() {

    long num = 0;

    public void update(long bytesRead, long contentLength, int items) {

      

            long progress = bytesRead*100/contentLength;

           if(progress==num)

               return;

           num = progress;

           System.out.println("上傳進度:" + progress + "%");

      

        //  request.getSession().setAttribute("progress", progress);

        }

    });

 

2. 在 jsp 頁面顯示進度

    實驗: 

    1) 使用 iframe 發送請求, 請求一個Servlet, 在Servlet 中返回響應,發送自增的num

       此時會發現 iframe 會不停第想Servlet發送請求

    2) 點擊文件上傳按鈕後,iframe立刻停止刷新,直至上傳完畢頁面跳轉至新頁面

    3)爲了觀察實驗結果,將form 的 target 指定爲 iframe, UploadServlet回送上傳完畢的結果

    4) 出現上述問題的原因,瀏覽器不支持多線程同時訪問服務器只能同時發送一個請求,

       這樣的訪問方式爲同步訪問

    5) 要在文件上傳的同時在iframe中實現進度訪問,就需要ie瀏覽器與服務器進行異步交互

       此時就需要 XMLHttpRequest 對象

       在javascript中可以直接使用XMLHttpRequest 對象與服務器進行異步通信

       獲得XmlHttpRequest 對象的方式有兩種

       ie7以上版本

       var xhr = null;

       if(window.XMLHttpRequest)

           xhr = new XMLHttpRequest();

       ie7以下版本

       if(window.ActiveXObject)

           xhr = new ActiveXObject(“Microsoft.XMLHTTP”);

      

       獲得對象後需要調用open方法輸入請求地址

       注意請求方式, 地址的輸入, 並且需要設置爲true 指定異步訪問該地址

       xhr.open(“get”,”/upload/servlet/UploadServlet”, false)

      

       // 調用send 方法發送請求,post方式需要發送消息體,get方式則不用直接傳入null值

       xhr.send(null);

      

       // 訪問 responseText 屬性獲得 Servlet 回送的數據

       document.write(xhr.responseText);

 

四、 api方法

1. DiskFileItemFactory 對象

    設置緩衝區大小,字節爲單位,默認爲10K,一般不用修改

    factory.setSizeThreshold(1000);

    設置臨時文件存放目錄

    factory.setRepository(file);

 

2. ServletFileUpload 對象

    判斷是否爲文件上傳表單

    boolean b = upload.isMultipartContent(request);

   解析request對象

   List<FileItem> list = upload.parseRequest(request);

   設置上傳文件的最大值

    setFileSizeMax(long fileSizeMax)

    設置上傳文件總量的最大值

    setSizeMax(long sizeMax)

    設置編碼格式

    setHeaderEncoding(java.lang.String encoding)

    註冊進度監聽器

    setProgressListener(ProgressListener pListener)

 

3. FileItem 對象

    獲得表單字段的屬性名

    item.getFieldName();

    獲得普通字段的值

    item.getString(charsetName)

    獲得文件上傳字段的文件名

    item.getName()

    獲得文件上傳的流

    item.getInputStream()

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章