1. 程式人生 > >Servlet 3.0改進的API 實現檔案上傳

Servlet 3.0改進的API 實現檔案上傳

1、Servlet 3.0 對檔案上傳的支援

Servlet 3.0 改進了部分API,使得java web 的開發進一步得到簡化。
其中兩個較大的改進是:

  • HttpServletRequest 增加了對檔案上傳的支援
  • ServletContext 允許通過程式設計的方式動態註冊Servlet、Filter

HttpServletRequest 提供瞭如下兩個方法來處理檔案上傳 :

  • Part getPart(String name) : 根據檔案上傳域name屬性來獲取上傳檔案。
  • Collection< Part > getParts() :獲取所有的檔案上傳域。

官方文件對這兩個方法的說明為:
這裡寫圖片描述


這裡寫圖片描述

上面兩個方法的返回值都涉及一個API :Part ;每個Part物件對應於一個檔案上傳域,該物件提供了大量方法來訪問上傳的檔案,如檔案型別、大小等。並提供了一個write(String name)將檔案寫入伺服器硬碟。

上傳檔案表單 :
為了向伺服器上傳檔案,需要在表單裡使用 < input type=”file” name=”xxx” …./>檔案域,這個檔案域會在HTML頁面生成一個單行文字框和一個用於“瀏覽檔案”的button。除此之外,表單必須設定enctype屬性
enctype屬性指定的是表單資料的編碼方式,該屬性有如下三個值:

  • application/x-www-form-urlencoded :這是預設的編碼方式,他只處理表單域裡的value屬性值,採用這種編碼方式的表單會將表單域的值處理成URL編碼方式
  • multipart/form-data : 這種方式會以二進位制流的方式來處理表單資料,這種編碼方式會把 檔案域指定檔案的內容 (並不是原檔案,而是檔案內容)也封裝到請求引數裡
  • text/plain : 這種編碼方式當表單的action 屬性為 mailto:URL 時比較方便,主要用於直接通過表單傳送郵件

如果將enctype設定為 application/x-www-form-urlencoded ,或者不設定enctype屬性,提交表單時只會傳送檔案域文字框裡的字串,也就是瀏覽者所選擇檔案的絕對路徑。這對伺服器來說沒多大用處,畢竟伺服器又無法訪問客戶機的檔案系統。

Servlet實現檔案上傳程式碼:

使用Servlet實現檔案上傳非常簡單,不需要commons-fileupload 等工具。注意匯入servlet-api.jar
表單示例:

    <form action="upload" method="post" enctype="multipart/form-data">
      <input type="file" name="file">
      <input type="submit" value="submit">
    </form>

Servlet示例:

/**@MultipartConfig
 * 不指定location屬性時,在IDEA環境下,part.write(fileName);上傳檔案預設儲存到以下地址
 *      C:\Users\Windward\.IntelliJIdea2017.1\system\tomcat\index_jsp_upLoad\work\Catalina\localhost\ROOT下
 * 指定location屬性,需要手動建立資料夾
 * 1.相對路徑時:如 location = "/uploadFiles"
 *  儲存地址為:E:\apache-tomcat-8.0.24\work\Catalina\localhost\upLoad_war_exploded\uploadFiles
 * 2.絕對路徑時:如 location = "F:\\uploadFiles"
 *  儲存至絕對路徑下,如 F:\uploadFiles下
 *
 */
@javax.servlet.annotation.MultipartConfig(location = "F:\\uploadFiles")
@javax.servlet.annotation.WebServlet(name = "upload",urlPatterns={"/upload"})
public class UploadServlet extends javax.servlet.http.HttpServlet {
    protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {

        //設定請求的編碼方式
        request.setCharacterEncoding("utf-8");
        //設定響應內容,與編碼
        response.setContentType("text/html;charset=utf-8");
        //獲取輸出流,輸出到客戶端瀏覽器
        PrintWriter out = response.getWriter();
        //獲取檔案上傳域 "file"域,Part物件封裝了獲取的檔案
        Part part = request.getPart("file");
        //獲取檔案型別
        String fileType = part.getContentType();
        //獲取檔案大小
        Long size= part.getSize();
        //獲取檔案上傳域的所有headerName
        Collection<String> headerNames = part.getHeaderNames();
        //獲取包含原始檔名的字串
        String fileNameInfo = part.getHeader("content-disposition");
        //提取上傳檔案的原始檔名
        String fileName = fileNameInfo.substring(fileNameInfo.indexOf("filename=")+10,
                                                    fileNameInfo.length()-1);
       //將檔案寫入伺服器硬碟,存入的檔名為fileName(write的引數),
        // 路徑為@MultipartConfig(location = "/uploadFiles")location屬性值
        part.write(fileName);

        out.println("<html>");
        out.println("<body>");
        out.print("檔名:"+fileName+"<br/>");
        out.print("檔案型別:"+fileType+"<br/>");
        out.print("檔案大小(byte):"+size+"<br/>");
        //遍歷列印檔案上傳域的所有 HeaderName-Value
        for (String headerName: headerNames ) {
            out.print("------------------------------------------------------------------"+"<br/>");
            out.print("headerName :"+headerName+"<br/>");
            //輸出headerName對應的value值
            out.print("value:"+part.getHeader(headerName) +"<br/>");
            out.print("------------------------------------------------------------------"+"<br/>");
        }
        out.println("</body>");
        out.println("</html>");
        out.close();

    }

    protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
        doPost(request,response);
    }
}