enctype 有三種屬性:
實務上表格通常不會只有一個上傳檔案,會同時包含文字輸入,按鈕選項,下拉式選單等等。這時候如果使用request.getParameter()讀取資料,你會發現都拿到null!!!。因為表格的enctype 屬性已經設定成multipart/form-data,資料是以binary傳輸,Servlet 2.x版本的request.getParameter() 預設是不會處理binary的資料,所以得到的值都是null.
如果採用第一種方法那就需要將全部資料從binary截取,那實在太麻煩了。那我們用第三方套件幫組我們完成這件事。
2. 使用第三方套件 Commons File Upload
下載 commons-fileupload.jar 和 commons-io.jar 然後引入到專案中.
- application/x-www-form-urlencoded:默認編碼方式(只是處理表單裡value屬性值)
- multipart/form-data:會以binary的編碼方式處理數據
- text/plain :空格轉為"+",但不对特殊字元編碼
既然需要實現檔案上傳, 那我們的enctype當然要用multipart/form-data這個屬性。
index.html
Servlet 2.x 的版本有兩種方法可以獲取上傳的檔案。
1.使用getInputStream()處理binary資料
index.html
<!DOCTYPE html> <html> <head> <title>文件上傳</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> </head> <body> <div> <form action="upload" method="POST" enctype="multipart/form-data"> <table> <tr> <td><label for="file1">文件:</label></td> <td><input type="file" id="file" name="file"></td> </tr> <tr> <td colspan="2"><input type="submit" value="上传" name="upload"></td> </tr> </table> </form> </div> </body> </html>
Servlet 2.x 的版本有兩種方法可以獲取上傳的檔案。
1.使用getInputStream()處理binary資料
package servlet.upload.demo; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/upload") public class UploadServlet extends HttpServlet { class Position { int begin; int end; public Position(int begin, int end) { this.begin = begin; this.end = end; } } private static final long serialVersionUID = -4673819464292623830L; public UploadServlet() { super(); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { byte[] content = bodyContent(request); // 讀取HTTP Body的內容 String contentAsTxt = new String(content, "ISO-8859-1"); // 將HTTP Body內容用String表示 String filename = getFileName(contentAsTxt); // 取得檔案名稱 Position p = getFilePosition(contentAsTxt, request.getContentType()); // 取得檔案開始和結束位置 writeTo(filename, content, p); } private byte[] bodyContent(HttpServletRequest request) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); InputStream in = request.getInputStream(); try { byte[] buffer = new byte[1024]; int length = -1; while ((length = in.read(buffer)) != -1) { out.write(buffer, 0, length); } } catch (Exception e) { e.printStackTrace(); } return out.toByteArray(); } private String getFileName(String requestBody) { String fileName = requestBody.substring(requestBody.indexOf("filename=\"") + 10); fileName = fileName.substring(0, fileName.indexOf("\n")); fileName = fileName.substring(fileName.indexOf("\n") + 1, fileName.indexOf("\"")); return fileName; } private Position getFilePosition(String content, String contentType) throws IOException { String boundaryText = contentType.substring(contentType.lastIndexOf("=") + 1, contentType.length()); // 取得實際上傳檔案的起始与结束位置 int pos = content.indexOf("filename=\""); pos = content.indexOf("\n", pos) + 1; pos = content.indexOf("\n", pos) + 1; pos = content.indexOf("\n", pos) + 1; int boundaryLoc = content.indexOf(boundaryText, pos) - 4; int begin = ((content.substring(0, pos)).getBytes("ISO-8859-1")).length; int end = ((content.substring(0, boundaryLoc)).getBytes("ISO-8859-1")).length; return new Position(begin, end); } private void writeTo(String fileName, byte[] body, Position p) throws IOException { FileOutputStream fileOutputStream = new FileOutputStream("d:/" + fileName); fileOutputStream.write(body, p.begin, (p.end - p.begin)); fileOutputStream.flush(); fileOutputStream.close(); } }
實務上表格通常不會只有一個上傳檔案,會同時包含文字輸入,按鈕選項,下拉式選單等等。這時候如果使用request.getParameter()讀取資料,你會發現都拿到null!!!。因為表格的enctype 屬性已經設定成multipart/form-data,資料是以binary傳輸,Servlet 2.x版本的request.getParameter() 預設是不會處理binary的資料,所以得到的值都是null.
如果採用第一種方法那就需要將全部資料從binary截取,那實在太麻煩了。那我們用第三方套件幫組我們完成這件事。
2. 使用第三方套件 Commons File Upload
下載 commons-fileupload.jar 和 commons-io.jar 然後引入到專案中.
package servlet.upload.demo; import java.io.File; import java.util.List; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; @WebServlet("/upload") public class UploadServlet2 extends HttpServlet { private static final long serialVersionUID = 2372213113534302476L; public UploadServlet2() { super(); } protected void doPost(HttpServletRequest request, HttpServletResponse response) { try { //檢查請求是否用multipart/form-data處理 if (ServletFileUpload.isMultipartContent(request)) { DiskFileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); //解析請求 ListformItems = upload.parseRequest(request); if (formItems != null && formItems.size() > 0) { for (FileItem item : formItems) { //檢查內容是檔案還是文字 if (!item.isFormField() && item.getName() != null && !item.getName().equals("")) { String fileName = new File(item.getName()).getName(); String filePath = "D:" + File.separator + fileName; File storeFile = new File(filePath); item.write(storeFile); } else { System.out.println("Key="+item.getFieldName()); System.out.println("Value="+item.getString()); } } } } } catch (Exception e) { e.printStackTrace(); } } }
3.使用Servlet 3.0 @MultipartConfig
Servlet 3.0 開始HttpServletRequest提供上傳檔案的支持。
package servlet.upload.demo; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.MultipartConfig; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Part; @MultipartConfig(location = "d:/") @WebServlet("/upload") public class UploadServlet3 extends HttpServlet { public UploadServlet3() { super(); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); // 處理中文檔名 Part part = request.getPart("file"); part.write(part.getSubmittedFileName()); } }
沒有留言:
張貼留言