SpringBoot_捕获文件传输异常

springBoot 默认传输文件大小未1M,超过1M的情况下会报错。(以下传输格式均为multipart/form-data)

2019-07-27 20:38:40.147 ERROR 15788 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : 
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is 
org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size exceeded; nested exception is java.lang.IllegalStateException: 
org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException:
 the request was rejected because its size (35020920) exceeds the configured maximum (10485760)] with root cause

org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (35020920) exceeds the configured maximum (10485760)
	at org.apache.tomcat.util.http.fileupload.FileUploadBase$FileItemIteratorImpl
....

修改的做法为:(springBoot v2.1.6.RELEASE)

#配置文件传输
spring.servlet.multipart.enabled=true  
spring.servlet.multipart.file-size-threshold=0
#单个文件的最大上限
spring.servlet.multipart.max-file-size=100MB
#单个请求的文件总大小上限
spring.servlet.multipart.max-request-size=1000MB

我们可以看看Springboot是怎么判断文件过大的。(使用工具Postman发送请求和wireshark抓包)

SpringBoot_捕获文件传输异常_第1张图片

实际上我们发送的是一个30MB左右的文件,但是把Content-length设置为了1.0GB左右,Springboot的阈值设置为1000M。这个请求会很快被拦截并且返回500的错误。所以应该就是通过Content-type和Content-length去判断一个MultipartFile的大小了。

可以再看看wiresharkSpringBoot_捕获文件传输异常_第2张图片

 这里我们可以确定了http报文的发送顺序了,显示发送首部,然后发送实体部分。而且http/1.1是使用持续化、管道化的连接,也就是不用等待请求,只要tcp窗口允许,就可以持续的发送数据。最终等到服务器处理完首部信息,返回500应答之前,它都会一直的发送数据。SpringBoot_捕获文件传输异常_第3张图片

有趣的是,在服务器返回应答之后,客户端Postman并没有停止发送数据。但是服务器并没有再此接受数据了。等到客户端处理完应答,便会主动断开连接。(这个只是个人实践结论。)SpringBoot_捕获文件传输异常_第4张图片

实际应用中这种设置是不满足我们的需求的,因为在传输文件超过设置阈值后,会报500的错误。所以我们应该拦截这个异常,返回我们需要的内容。

另外一个问题,如果是在controller获知service中做文件大小的限制,那么在限制文件大小为20M,可是上传文件大小为1G的情况下,需要等1G文件上传完毕后,才能进入controller进行拒绝应答,这也是个很大的问题。

解决方法之一:

package com.gtn.uplus.filemgr.errutil;

import com.gtn.uplus.filemgr.domain.response.UploadFileResp;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MultipartException;

/**
 * @author :Czc
 * @date :Created in 2019/7/26 15:30
 * @description:
 * @modified By:
 * @version: $
 */
@RestControllerAdvice
public class MyExceptionHandler {
    /***
     *  默认上传大小20MB 超出大小捕获异常MultipartException
     *  */
    @ExceptionHandler(MultipartException.class)
    public UploadFileResp catchException(MultipartException e) {
        return new UploadFileResp(ErrNo.ERROR_CONTENT_LIMITED,ErrNo.getErrorInfo(ErrNo.ERROR_CONTENT_LIMITED),null);
    }
}

 

 

 

 

你可能感兴趣的:(spring,web)