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);
//解析請求
List formItems = 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());
}
}
沒有留言:
張貼留言