在以前,处理文件上传是一个很痛苦的事情,大都借助于开源的上传组件,诸如commons fileupload等。现在好了,很方便。以前的HTML端上传表单不用改变什么,还是一样的multipart/form-data MIME类型。
让Servlet支持上传,需要做两件事情
- 需要添加MultipartConfig注解
- 从request对象中获取Part文件对象
但在具体实践中,还是有一些细节处理,诸如设置上传文件的最大值,上传文件的保存路径。
需要熟悉MultipartConfig注解,标注在@WebServlet之上,具有以下属性:

实践建议:
- 若是上传一个文件,仅仅需要设置maxFileSize熟悉即可。
- 上传多个文件,可能需要设置maxRequestSize属性,设定一次上传数据的最大量。
- 上传过程中无论是单个文件超过maxFileSize值,或者上传总的数据量大于maxRequestSize值都会抛出IllegalStateException异常;
- location属性,既是保存路径(在写入的时候,可以忽略路径设定),又是上传过程中临时文件的保存路径,一旦执行Part.write方法之后,临时文件将被自动清除。
- 但Servlet 3.0规范同时也说明,不提供获取上传文件名的方法,尽管我们可以通过part.getHeader("content-disposition")方法间接获取得到。
- 如何读取MultipartConfig注解属性值,API没有提供直接读取的方法,只能手动获取。
实例:
上传jsp页面源码
index.jsp
后台servlet处理源码:
UploadFileServlet.java
上传jsp页面源码
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>web3.0文件上传</title>
</head>
<body>
<div>
<form method="post" enctype="multipart/form-data" action="upload.do">
<input type="file" id="file" name="file" /> <br>
<input type="submit" value="提交" />
</form>
</div>
</body>
</html>
后台servlet处理源码:
UploadFileServlet.java
package cn.kpchen.servlet;
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;
@WebServlet(urlPatterns = "/upload.do")
@MultipartConfig(fileSizeThreshold = 10, location = "D:/", maxFileSize = 1024 * 100 * 1000, maxRequestSize = -1)
// fileSizeThreshold int 当数据量大于该值时,内容将被写入文件。单位:byte
// location String 存放生成的文件地址。
// maxFileSize long 允许上传的文件最大值。默认值为 -1,表示没有限制。单位:byte
// maxRequestSize long 针对该 multipart/form-data 请求的最大数量,默认值为 -1,表示没有限制。单位:byte
public class UploadFileServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
// 得到注解信息
private static final MultipartConfig config;
static {
config = UploadFileServlet.class.getAnnotation(MultipartConfig.class);
System.out.println(config);
}
public UploadFileServlet() {
super();
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=utf-8");
response.setCharacterEncoding("UTF-8");
Part part = null;
try {
part = request.getPart("file");
} catch (IllegalStateException e) {
if (config.maxFileSize() == -1) {
System.out
.println("the Part in the request is larger than maxRequestSize");
} else if (config.maxRequestSize() == -1) {
System.out
.println("the request body is larger than maxFileSize");
} else {
System.out
.println("the request body is larger than maxRequestSize, or any Part in the request is larger than maxFileSize");
}
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ServletException e) {
e.printStackTrace();
}
if (part == null) {
System.out.println("上传文件出现异常,请检查输入是否有误");
return;
}
String fileName = getFileName(part);
System.out.println("contentType : " + part.getContentType());
System.out.println("fileName : " + fileName);
System.out.println("fileSize : " + part.getSize());
System.out.println("header names : ");
for (String headerName : part.getHeaderNames()) {
System.out.println(headerName + " : " + part.getHeader(headerName));
}
String saveName = System.currentTimeMillis()
+ fileName.substring(fileName.lastIndexOf("."));
System.out.println("save the file with new name : " + saveName);
// 因在注解中指定了路径,这里可以指定要写入的文件名
// 在未执行write方法之前,将会在注解指定location路径下生成一临时文件
part.write(saveName);
response.getWriter().write("上传成功");
}
protected String getFileName(Part part) {
// Servlet
// 3.0规范说明,不提供获取上传文件名的方法,可以通过part.getHeader("content-disposition")方法间接得到。
if (part == null)
return null;
String fileName = part.getHeader("content-disposition");
if (fileName == null || fileName.trim().length() == 0) {
return null;
}
return fileName.substring(fileName.indexOf("filename=\"") + 10,
fileName.lastIndexOf("\""));
}
}