Servlet3.0文件上传
1.Sevlet3.0提供了一个新API来处理上传数据:
- Annotation MultipartConfig: A servlet can be annotated with this annotation in order to handlemultipart/form-data requests which contain file upload data.
通过这个注解标记一个Servlet 可以处理multipart/form-data请求包含的文件上传操作。
annotation has the following options:
-
- fileSizeThreshold: file’s size that is greater than this threshold will be directly written to disk, instead of saving in memory.
如果上传的文件内容长度大于此值,将会写入磁盘而不保存在内存中。 - location: directory where file will be stored via Part.write() method.
文件保存的本地路径 - maxFileSize: maximum size for a single upload file.
单次上传文件长度最大值,此值为字节 - maxRequestSize:maximum size for a request.
单次上传文件长度最大值,此值为字节所有size单位为字节,-1L表示不限制。1024*1024*10 = 10 MB
- fileSizeThreshold: file’s size that is greater than this threshold will be directly written to disk, instead of saving in memory.
-
- Interface Part: represents a part in a multipart/form-data request. This interface defines some methods for working with upload data (to name a few):
-
- getInputStream(): returns an InputStream object which can be used to read content of the part.
获取上传文件的文件流 - getSize(): returns the size of upload data, in bytes.
文件大小 - write(String filename): this is the convenience method to save upload data to file on disk. The file is created relative to the location specified in the MultipartConfig annotation.
- getInputStream(): returns an InputStream object which can be used to read content of the part.
-
- New methods introduced in HttpServletRequest interface:
- getParts(): returns a collection of Part objects
获取多个上传文件对象 - getPart(String name): retrieves an individual Part object with a given name.
获取指定名name的上传文件对象。<input type="file" name="abc">
- getParts(): returns a collection of Part objects
示例代码---服务端:
@WebServlet(urlPatterns = "/upload.html")
@MultipartConfig(fileSizeThreshold = 1024 * 1024 * 2, maxFileSize = 1024 * 1024 * 10, maxRequestSize = 1024 * 1024 * 50)
public class UploadFileServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("UploadFileServlet doPost invoked!");
for (Part part : req.getParts()) {
String fileName = extractFileName(part);
part.write("D://xxx_"+fileName);
/*
* System.out.println("fileName=" + fileName); InputStream is =
* null; OutputStream os = null; try { is = part.getInputStream();
* os = new FileOutputStream(new File("D://xxx_" + fileName));
* byte[] buf = new byte[1024]; int len = 0; while ((len =
* is.read(buf)) != -1) { os.write(buf, 0, len); } } catch
* (Exception e) { } finally { if (is != null) { os.close();
* is.close(); } }
*/
}
resp.setCharacterEncoding("utf-8");
resp.getWriter().println("上传文件成功!");
resp.getWriter().close();
}
/**
* Extracts file name from HTTP header content-disposition
*/
private String extractFileName(Part part) {
String contentDisp = part.getHeader("content-disposition");
String[] items = contentDisp.split(";");
for (String s : items) {
if (s.trim().startsWith("filename")) {
return s.substring(s.indexOf("=") + 2, s.length() - 1);
}
}
return "";
}
}
客户端:此处使用Jsoup代码的方式上传文件,而不是通过浏览器。不熟悉Jsoup的可以参数我另一篇博文“
HttpClient/Jsoup 请求”
public static void main(String[] args) {
InputStream is = null;
try {
String url = "http://localhost:8080/part1/upload.html";
is = new FileInputStream(new File("D://abc.txt"));
Response response = Jsoup.connect(url).data("gdr", "abcc.txt", is).method(Method.POST).execute();
System.out.println(response.body());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
输出:
上传文件成功!
注:该代码在Eclipse-Jetty插件中运行,一直没有将文件写入D://下。但在Tomcat中运行,一切正常。
造成这种现象很容易理解,Servlet为接口规范,其实现为各Web容器。
因此建议在保存文件时为了保证在各种Web容器中运行都有一至结果,建议通过Part接口获取文件输入流,自己实现文件保存功能。如示例中的注释。