【SpringMVC】---- 设置最大文件上传大小后,发送超过最大上传大小后,网页却出现连接被重置【已解决】

一、情况演示

  1. SpringMVC-servlet.xml

    
        <bean id="multipartResolver"
              class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> 
            
            <property name="defaultEncoding" value="UTF-8"/>
            
            <property name="maxUploadSize" value="5485760">property> 
        bean>
    

    这里设置了文件上传大小最大为5M,小于5M,则文件上传成功,大于5M,则文件上传失败

  2. 文件小于5M上传成功
    【SpringMVC】---- 设置最大文件上传大小后,发送超过最大上传大小后,网页却出现连接被重置【已解决】_第1张图片
    【SpringMVC】---- 设置最大文件上传大小后,发送超过最大上传大小后,网页却出现连接被重置【已解决】_第2张图片

  3. 文件大于5M上传失败
    【SpringMVC】---- 设置最大文件上传大小后,发送超过最大上传大小后,网页却出现连接被重置【已解决】_第3张图片
    【SpringMVC】---- 设置最大文件上传大小后,发送超过最大上传大小后,网页却出现连接被重置【已解决】_第4张图片

二、原因及解决方案

  1. 原因
    这里其实是tomcat版本出现了问题,如果使用apache-tomcat-7.0.39这个版本的tomcat,上面的配置就是正确的,不会出现该问题, 但是如果是其他版本的tomcat,那么就会出现上面连接重置问题,传送门看详情

    When uploading a large file, larger than the specified maximum, the exception org.springframework.web.multipart.MaxUploadSizeExceededException (caused by a org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException) is caught via an @ExceptionHandler. After logging the exception and resolving some parameters from the inputstream a redirect is performed like this:
    return new org.springframework.web.servlet.ModelAndView(“redirect:/error”, new org.springframework.ui.ExtendedModelMap());
    I expect that this would generate a HTTP 302 redirect and will trigger a GET request on “/error”. The upload obviously is a POST request and the redirect would perform a GET request. Tomcat version 7.0.54 and .53 indeed do that, but in version 55 and up it remains a POST request. The complete multipart content-type is saved and the whole request is repeated until the server throws an error: (failed) net::ERR_CONNECTION_RESET.
    当上传大于指定最大值的大文件时,通过@ExceptionHandler捕获异常org.springframework.web.multipart.MaxUploadSizeExceededException(由org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException引起)。在记录了异常并从inputstream中解析了一些参数之后,将执行重定向,如下所示:
    返回新的org.springframework.web.servlet.ModelAndView(“ redirect:/ error”,新的org.springframework.ui.ExtendedModelMap());
    我希望这将生成HTTP 302重定向,并在“ /错误”上触发GET请求。上载显然是POST请求,重定向将执行GET请求。Tomcat 7.0.54和.53版确实可以做到这一点,但是在55版及更高版本中,它仍然是POST请求。保存完整的多部分内容类型,并重复整个请求,直到服务器抛出错误:(失败)net :: ERR_CONNECTION_RESET。

  2. 解决方案
    在文章中说明了这可能是tomcat服务器的bug问题,而非Spring MVC框架问题,如果使用tomcat7.0.39版本的话,这个问题就不存在了; 另外一种思路: 使用SpringMVC拦截器

    • 在Springmvc-servlet.xml文件中加入拦截器配置

       
          <bean id="multipartResolver"
                class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> 
              
              <property name="defaultEncoding" value="UTF-8"/>
              
              
          bean>
          
          <mvc:interceptors>
              <mvc:interceptor>
                  <mvc:mapping path="/**"/>
                  <bean class="com.javaee.ch16.interceptor.FileUploadInterceptor">
                      
                      <property name="maxSize" value="5485760"/>
                  bean>
              mvc:interceptor>
          mvc:interceptors>
      
    • 创建FileUploadInterceptor拦截器类

      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对象
      			ServletRequestContext ctx = new ServletRequestContext(request);
      			// 获取资源大小
      			long requestSize = ctx.contentLength();
      			// 判断资源大小是否是大于在xml配置中设置的最大5M文件上传大小,如果是,抛出异常信息
      			if(requestSize > maxSize) {
               
      				throw new MaxUploadSizeExceededException(maxSize);
      			}
      		}
      		// 如果没有超出5M大小,则直接返回true
      		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;
      	}
      }
      
    • 在上传文件Controller类中添加局部异常类方法进行捕捉异常,用@ExceptionHandler

      @ExceptionHandler
      	public String handleException(Exception ex, HttpServletRequest request, HttpServletResponse response) throws IOException {
               
      		// 处理文件上传过大异常
      		if (ex instanceof MaxUploadSizeExceededException) {
               
      			ex.printStackTrace();
      			System.out.println(ex);
      			// 文件最大上传大小
      			long allowedMaxFileSize = ((MaxUploadSizeExceededException) ex).getMaxUploadSize();
      			// 获取文件的上传大小
      			long theFileSize = ((DefaultMultipartHttpServletRequest) request).getRequest().getContentLength();
      			// byte转换为MB
      			int fileSizeUnit = 1000000;
      			// 在request域中保存信息
      			// theMessage : 文件大小文件大小12.549671MB, 超过了5.48576MB
      			request.setAttribute("theMessage", "文件大小" + (theFileSize * 1.0 / fileSizeUnit)
      					+ "MB, 超过了" + (allowedMaxFileSize * 1.0 / fileSizeUnit) + "MB");
      		}
      		// 跳转到错误界面
      		return "error";
      	}
      
      【SpringMVC】---- 设置最大文件上传大小后,发送超过最大上传大小后,网页却出现连接被重置【已解决】_第5张图片

参考:
https://blog.csdn.net/w47_csdn/article/details/76422357
https://www.cnblogs.com/antis/p/7063746.html
https://bz.apache.org/bugzilla/show_bug.cgi?id=57438#c1

后续
原来老师给的场景是总文件上传大小未超过,而是单个文件大小超过了限制,在Controller代码中控制单个文件大小及判断就好!!!

你可能感兴趣的:(平时遇到的坑)