controller类:
@RequestMapping(path = "/file", method = RequestMethod.POST)
public UploadMsg uploadFile(@RequestParam("uploadFile") MultipartFile file, String userCode) throws Exception {
String fileId = genFileId();
saveFileToSystem(file, fileId);
UploadMsg uploadMsg = getUploadMsg(userCode, fileId, file.getSize());
return uploadMsg;
}
@ExceptionHandler(MaxUploadSizeExceededException.class)
public ResponseEntity<String> handleException(MaxUploadSizeExceededException ex) {
System.out.println("=====================" + ex.getClass().getName());
return ResponseEntity.ok("ok");
}
spring配置文件配置文件大小不能超过1M
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"/>
<property name="maxUploadSize" value="#{1*1024*1024}"/>
<property name="resolveLazily" value="true"/>
</bean>
下面是我用小于1M的文件访问时的情况
这是上传失败的情况
下面是我的日志打印情况
22:40:28,569 DEBUG http-apr-8080-exec-5 support.DefaultListableBeanFactory:251 - Returning cached instance of singleton bean 'uploadFileController'
=====================org.springframework.web.multipart.MaxUploadSizeExceededException
22:40:28,574 WARN http-apr-8080-exec-5 commons.CommonsMultipartResolver:194 - Failed to perform multipart cleanup for servlet request
org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size of 1048576 bytes exceeded; nested exception is org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (6145455) exceeds the configured maximum (1048576)
at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:162)
at org.springframework.web.multipart.commons.CommonsMultipartResolver$1.initializeMultipart(CommonsMultipartResolver.java:134)
at org.springframework.web.multipart.support.AbstractMultipartHttpServletRequest.getMultipartFiles(AbstractMultipartHttpServletRequest.java:126)
at org.springframework.web.multipart.support.AbstractMultipartHttpServletRequest.getMultiFileMap(AbstractMultipartHttpServletRequest.java:106)
at org.springframework.web.multipart.commons.CommonsMultipartResolver.cleanupMultipart(CommonsMultipartResolver.java:191)
at org.springframework.web.servlet.DispatcherServlet.cleanupMultipart(DispatcherServlet.java:1107)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:895)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:869)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
at org.apache.catalina.core.StandardContextValve.__invoke(StandardContextValve.java:106)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.__invoke(StandardHostValve.java:141)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2500)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2489)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (6145455) exceeds the configured maximum (1048576)
at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:968)
at org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:310)
at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:334)
at org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:115)
at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:158)
... 35 more
=====================org.springframework.web.multipart.MaxUploadSizeExceededException
这句是我在@ExceptionHandler(MaxUploadSizeExceededException.class)注解的方法中打印的。
解决方案:
当看到这文章的时候相信你现在应该遇到这样的问题了,我也是自己遇到了后来找到解决方案了记录下来,如果下次遇到就可以直接解决了。
至于为什么会出现这样的情况,可以看这篇文章:https://bz.apache.org/bugzilla/show_bug.cgi?id=57438
在文章中说明了这可能是tomcat服务器的bug问题,而非Spring MVC框架问题,如果使用tomcat7.0.39版本的话,这个问题就不存在了。
所以针对Spring MVC文件上传大小限制出现的这个问题,可以换用tomcat7.0.39版本的tomcat服务器;或者使用另一种思路:
首先,把maxUploadSize 设置大一点,让它不会抛异常出来,配置如下:
<!-- 多部分文件上传 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 最大上传大小,不能超过40M @see #FileUploadInterceptor -->
<property name="maxUploadSize" value="41943040"/>
<property name="maxInMemorySize" value="4096"/>
<property name="defaultEncoding" value="UTF-8"/>
</bean>
或者不使用Spring MVC提供的文件上传大小限制属性<property name="maxUploadSize" value="5242880" /> 配置如下:
<!-- 配置文件上传类型解析器 multipartResolver-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
然后创建一个拦截器控制上传大小,然后抛出同样的异常出来,或者也可以直接在拦截器中处理异常。
public class FileUploadInterceptor implements HandlerInterceptor {
private long maxSize;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if(request!=null && ServletFileUpload.isMultipartContent(request)) {
ServletRequestContext ctx = new ServletRequestContext(request);
long requestSize = ctx.contentLength();
if (requestSize > maxSize) {
throw new MaxUploadSizeExceededException(maxSize);
}
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
public void setMaxSize(long maxSize) {
this.maxSize = maxSize;
}
}
然后在spring-mvc.xml中配置
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.lvrounet.peiniang.interceptor.FileUploadInterceptor">
<property name="maxSize" value="4194304"/>
</bean>
<mvc:interceptor>
</mvc:interceptors>
这样就可以完成在Spring MVC环境下文件上传大小的限制以及异常正确捕获了。
在Controller类中进行异常捕捉或定义全局异常捕捉(略):
@ExceptionHandler
public ModelAndView handleException(Exception ex, HttpServletRequest request, HttpServletResponse response) throws IOException {
// 处理文件上传过大异常
if (ex instanceof MaxUploadSizeExceededException) {
ex.printStackTrace();
long maxSize = ((MaxUploadSizeExceededException) ex).getMaxUploadSize();
logger.error("File size can’t exceed " + maxSize / (1024*1024) + "M", ex);
CommonResult result = new CommonResult();
result.setResult(2);
result.setErrormsg("File size can’t exceed " + maxSize / (1024*1024) + "M");
response.setHeader("Content-type", "text/html;charset=UTF-8");
response.getWriter().write(result.toString());
}
return null;
}