使用spring mvc的MultipartFile对象上传文件时,发现上传1G的文件需要差不多1分钟左右才能进入到对应的Controller,而最可气的是我们上传文件时Header信息里面的Token认证信息,也是1分钟后才收到,导致我们Token认证信息经常验证超时(Token的有效期为30秒)。我们的Token验证时在拦截器里面进行的,先验证Token然后再处理上传逻辑。查看日志,发现上传时进入拦截器的时间与进入Controller的时间相差5毫秒,近乎同时。然而,我们项目上希望先验证Token,然后再上传文件,如果Token验证不通过,则直接返回验证失败,不要等文件上传完然后再提示验证失败。因为没有深入看spring mvc的源码,一时间找不到解决办法,请教了一个高手说改成Servlet上传就可以。于是照做: Java源码: import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.FileCleanerCleanup; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.FileCleaningTracker; import javax.servlet.ServletContext; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.UnsupportedEncodingException; import java.util.List; /** * @author Administrator */ public class UploadServlet extends HttpServlet { private static final long serialVersionUID = 1L; private static final int BUFFER_SIZE = 1024*1024; private static final int MAX_SIZE_PER_REQUEST = 1024*1024*1056; private static final int MAX_SIZE_PER_FILE = 1024*1024*1024; public UploadServlet() { super(); } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) { doPost(request,response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { boolean isMultipart = ServletFileUpload.isMultipartContent(request); if (isMultipart) { ServletContext servletContext = this.getServletConfig().getServletContext(); FileCleaningTracker fileCleaningTracker = FileCleanerCleanup.getFileCleaningTracker(servletContext); DiskFileItemFactory factory = new DiskFileItemFactory(); //清理临时文件 factory.setFileCleaningTracker(fileCleaningTracker); File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir"); //设置缓存大小 factory.setSizeThreshold(BUFFER_SIZE); factory.setRepository(repository); ServletFileUpload upload = new ServletFileUpload(factory); //将页面请求传递信息最大值设置为1056M upload.setSizeMax(MAX_SIZE_PER_REQUEST); //将单个上传文件信息最大值设置为1024M upload.setFileSizeMax(MAX_SIZE_PER_FILE); try { List<FileItem> items = upload.parseRequest(request); for (int i = items.size()-1; i >= 0 ; i--) { FileItem item = items.get(i); if (item.isFormField()) { String fieldName = item.getFieldName(); String fieldValue = item.getString("utf-8"); System.out.println("FileItem " + i + ":[fieldName:"+fieldName+",fieldValue:"+fieldValue+"]"); }else{ String saveDir = request.getSession().getServletContext().getRealPath("/upload"); File file = new File(saveDir, item.getName()); item.write(file); } } } catch (FileUploadException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } } } 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>Insert title here</title> </head> <body> <h1>文件上传</h1> <form method="POST" enctype="multipart/form-data" action="upload" name="uploadForm"> 选择一个文件: <input type="file" name="upfile"><br/> <br/> <input type="submit" value="上传"> </form> </body> </html> web.xml <servlet> <servlet-name>UploadServlet</servlet-name> <servlet-class>com.mingcloud.ams.controller.UploadServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>UploadServlet</servlet-name> <url-pattern>/upload</url-pattern> </servlet-mapping> 进行断点调试,发现局域网上传1G文件时,立即进入Servlet的doPost里面,可以立即获取到Token,然后进行验证,但是 执行upload.parseRequest(request)时73.182秒,执行到 item.write(file);时耗时1.277秒,整个上传过程耗时1.2分钟,计算了一下发现是10M/s的处理速度,局域网基本上就这样了。查看了parseRequest方法,发现是进行流的拷贝操作,原有这里这么耗时。在没有问高人前,一直怀疑是tomcat组包成request导致的时间长,现在一想tomcat太牛逼了,一个G的对象很快转换,估计是1秒内甚至是毫秒级完成。问题是解决了,还是想想为什么spring mvc那么久才进入controller吧。 查了些资料,说spring mvc 在进入controller 前先用SpringMVC解析器解析request请求参数并绑定数据到Controller的入参上,原来是将请求parseRequest后才形成MultipartFile;还有为什么spring mvc的拦截器进去时间和进入controller的时间相差无几,大胆猜想spring mvc的拦截器肯定是在SpringMVC解析器解析request请求参数并绑定数据到Controller的入参之后和进入controller之前拦截的,看来遇到问题还是要多看源码啊,多了解http协议的本质很重要。 性能测试: 文件大小<=255KB 80张/秒 文件大小<=1.44MB 50张/秒 文件大小<=826MB [20,30]并发请求都在处理,基本半小时都能够上传成功
<dependency> <groupId>com.github.mwiede</groupId> <artifactId>jsch</artifactId> <version>0.2.8</version> </dependency> TYPE="Ethernet" PROXY_METHOD="none" BROWSER_ONLY="no" BOOTPROTO="static" DEFROUTE="yes" IPV4_FAILURE_FATAL="no" IPV6INIT="yes" IPV6_AUTOCONF="yes" IPV6_DEFROUTE="yes" IPV6_FAILURE_FATAL="no" IPV6_ADDR_GEN_MODE="stable-privacy" NAME="enp65s0f0" UUID="94b2fde3-e7e1-42fc-b0a1-344efb8f1462" DEVICE="enp65s0f0" ONBOOT=yes IPADDR=192.168.1.168 NETMASK=255.255.255.0 GATEWAY=192.168.1.254 ZONE=public IPV6ADDR=2400:777:666:0:a:27ff:fed0:168 IPV6_DEFAULTGW=2400::1
相关推荐
springmvc上传文件controller,vue
基于springmvc实现文件上传下载 基于AOP的日志功能基于springmvc实现文件上传下载 基于AOP的日志功能基于springmvc实现文件上传下载 基于AOP的日志功能基于springmvc实现文件上传下载 基于AOP的日志功能基于...
springMvc 文件上传,springMvc 支持单文件和多文件上传,
springMVC多文件上传d
在上一篇SpringMVC基础教程的源码基础上增加了文件上传,多文件上传
SpringMVC文件上传与下载的实现,包括UploadController和DownloadController
SpringMVC单文件上传、多文件上传、文件列表显示、文件下载,具体效果和过程看博文http://blog.csdn.net/evankaka/article/details/45826697
springMVC 上传文件方式springMVC 上传文件方式springMVC 上传文件方式
springmvc 上传下载文件,支持 ajax,form 提交,支持 multiple 方式上传文件
本例子提供了2中 springMVC 上传的例子,通过 ajax 提交的方式,通过 Form 提交的方式,同时获取上传后文件名称,支持多个文件上传。
在使用springMVC进行系统实现时,springMVC默认的解析器里面是没有加入对文件上传的解析的,这可以方便我们实现自己的文件上传。但如果你想使用springMVC对文件上传的解析器来处理文件上传的时候就需要在spring的...
JavaEE企业级开发-----SpringMVC实现 文件的上传下载实验报告
springmvc中实现文件上传所要用到的jar包
开发工具:eclipse+tomcat+jdk1.7 基于springMVC的文件上传功能
SpringMVC文件的上传与下载(包括单一文件与多文件上传,两种下载方式)
个人整理-SpringMVC上传文件的四种方法,汉jar包,含计时
用springMVC 实现文件的上传、下载,含文件的压缩功能。
SpringMVC文件上传案例
springmvc带进度条上传源码