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接口获取文件输入流,自己实现文件保存功能。如示例中的注释。