springmvc对form表单的支持已经很成熟,仅仅两步:
- 配置支持文件上传的bean:org.springframework.web.multipart.commons.CommonsMultipartResolver
同时设置文件编码、单次提交表单上传文件最大字节数、以及写文件时使用的缓冲区大小 - 开发处理:handler[org.hy.ssm.web.controller.FormController.uploadOne(MultipartFile)]
- /**
- * @Title: uploadOne
- * @Description: 单文件上传
- * @param file
- * @return ModelMap
- */
- @RequestMapping("/uploadOne")
- @ResponseBody
- public ModelMap uploadOne(MultipartFile file) {
- final String UPLOAD_DIR = "/upload/";
- final String KEY_OF_ORIGINAL_FILE_NAME = "origFileName";
- final String KEY_OF_FILE_URL = "fileUrl";
- final String KEY_OF_FILE_SUFFIX = "fileSuffix";
- boolean flag = false;
- String message = null;
- Map<String, String> data = Maps.newHashMap();
- // 原文件名(通常用于下载展示)
- String originalFilename = file.getOriginalFilename();
- data.put(KEY_OF_ORIGINAL_FILE_NAME, originalFilename);
- // 文件类型(后缀)
- String suffix = FileUtil.getSuffix(originalFilename);
- data.put(KEY_OF_FILE_SUFFIX, suffix);
- // 目标文件名(通常情况需要重命名, 防止同名文件覆盖)
- String fileName = String.valueOf(System.currentTimeMillis()) + suffix;
- String fileUrl = (UPLOAD_DIR + fileName);
- data.put(KEY_OF_FILE_URL, fileUrl);
- try {
- File dest = WebUtil.getFile(fileUrl);
- file.transferTo(dest);
- flag = true;
- } catch (Exception e) {
- flag = false;
- message = "";
- LOGGER.warn(message + " : " + e.getMessage(), e);
- }
- return WebUtil.getModelMap(flag, data, message);
- }
接下来验证结果是否正确:
- 正常验证
- 非法验证,文件大小超出。当前测试数据70+MB
- org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size of 32505856 bytes exceeded; nested exception is org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (79882924) exceeds the configured maximum (32505856)
- at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:160)
- at org.springframework.web.multipart.commons.CommonsMultipartResolver.resolveMultipart(CommonsMultipartResolver.java:139)
- at org.springframework.web.servlet.DispatcherServlet.checkMultipart(DispatcherServlet.java:1020)
- at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:883)
- at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
- at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
- at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
- at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
- at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
- at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
- at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
- at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
- at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
- at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
- at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
- at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
- at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504)
- at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
- at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
- at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
- at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
- at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421)
- at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1074)
- at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
- at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
- at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
- at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
- at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
- at java.lang.Thread.run(Thread.java:722)
- Caused by: org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (79882924) exceeds the configured maximum (32505856)
- at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:937)
- at org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:331)
- at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:351)
- at org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:126)
- at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:156)
- ... 28 more
到此,单文件上传已经搞定。是不是很简单呢?当然了还有稍微原始的方法,通过 org.apache.commons.fileupload.servlet.ServletFileUpload 也能实现文件上传的功能,在此不做详解。大致步骤如下:
- 获取工厂 DiskFileItemFactory
- 通过工厂获取上传组件 ServletFileUpload
- 解析请求获取表单项
- 判断表单项类型
- 解析表单项
- /**
- * @Title: uploadByFileUpload
- * @Description: 使用Commons.FileUpload上传文件
- */
- @RequestMapping("/uploadByFileUpload")
- public void uploadByFileUpload() {
- final String UPLOAD_DIR = "upload/";
- final String basePath = WebUtil.getBaseFilPath();
- HttpServletRequest request = WebUtil.getRequest();
- try {
- // 防止中文名乱码
- request.setCharacterEncoding("utf-8");
- // 1. 获取工厂 DiskFileItemFactory
- DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();
- // 缓存区目录
- fileItemFactory.setRepository(new File(basePath + "tmp/"));
- // 缓存区大小
- fileItemFactory.setSizeThreshold(1024 * 6);
- // 2. 通过工厂获取上传组件 ServletFileUpload
- ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
- // 设置文件的大小为2M
- servletFileUpload.setSizeMax(1024 * 1024 * 2);
- // 防止中文乱码(文件名)
- servletFileUpload.setHeaderEncoding("UTF-8");
- // 3. 解析请求获取表单项
- @SuppressWarnings("unchecked")
- List<FileItem> items = servletFileUpload.parseRequest(request);
- // 4. 判断表单项类型
- for (FileItem item : items) {
- // 5. 解析表单项
- // 表单项名称
- String fieldName = item.getFieldName();
- if (item.isFormField()) {
- // 普通表单项处理
- String name = fieldName;
- String value = item.getString("UTF-8");
- System.out.println(name + ":" + value);
- } else {
- // 文件表单项
- // 获取文件名
- String originalFileName = item.getName();
- String suffix = FileUtil.getSuffix(originalFileName);
- String newFileName = String.valueOf(System.currentTimeMillis());
- // 写入文件
- String fileName = File.separator + newFileName + suffix;
- File newFile = FileUtil.createQuietly(basePath + UPLOAD_DIR + fileName);
- item.write(newFile);
- item.delete();
- }
- }
- } catch (Exception e) {
- LOGGER.warn(e.getMessage(), e);
- }
- }
注意:如果使用上面的方式获取上传文件,需要停止 springmvc 的文件解析机制,否则将不能获取数据 !!
源码下载:ssmFU.zip