SpringBoot上传文件限制

young 849 2021-11-04

项目中需要控制上传文件的大小,采用了SpringBoot中的配置进行配置,并添加了相关的异常拦截处理。

  • application.yaml
spring:
  servlet:
    multipart:
      max-file-size: 5MB     # 文件上传大小限制为5MB
      max-request-size: 5MB  # 请求大小限制为5MB

  • 全局异常配置
@RestControllerAdvice
public class CustomExceptionHandler {

    // 上传文件超过5M,捕获异常:MaxUploadSizeExceededException
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public ResutlCodeException handlerMaxUploadFile(MaxUploadSizeExceededException ex) {
        return new ResutlCodeException("文件大小不能超过5MB");
    }
}

在IEAD中启动项目,通过POSTMAN测试,可以正常拦截住超过限制的请求

将项目打包成war应用,部署在联调环境的Tomcat上,此时上传超过限制大小的文件,前端获取不到响应,处于无响应的情况,查看项目日志,发现没有任何相关日志。
推测此时请求被Tomcat中的相关配置拦截,未进入到Spring的校验中

修改tomcat下的配置tomcat_home/conf/server.xml,在Connector节点下增加maxSwallowSize="-1"的配置

<Connector port="8080" protocol="HTTP/1.1" maxSwallowSize="-1" connectionTimeout ="200000" redirectPort ="8443"/>
<!-- maxSwallowSize="-1"表示tomcat不做限制 -->
<!-- tomcat版本为8.5 -->

此时服务端能正常响应请求,但是统一异常处理依旧无法处理异常

此时创建一个拦截器,判断文件大小,当不满足限制时抛出相同的异常,并将拦截器注入到Spring中,即可时项目正确捕获异常

  • 拦截器
public class FileInterceptor implements HandlerInterceptor {
    private long maxSize;
    public FileInterceptor() {
	// BeanFactory为继承了ApplicationContextAware的自定义类
        MultipartProperties bean = BeanFactory.getBean(MultipartProperties.class);
        DataSize maxFileSize = bean.getMaxFileSize();
        this.maxSize = maxFileSize.toBytes();
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        if (request != null && ServletFileUpload.isMultipartContent(request)) {
            ServletRequestContext context = new ServletRequestContext(request);
	    // 获取文件大小
            long requestSize = context.contentLength();
            if (requestSize > maxSize) {
                throw new MaxUploadSizeExceededException(maxSize);
            }
        }
        return true;
    }
}
  • 注册拦截器,并将顺序放至最前
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new FileInterceptor())
                .addPathPatterns("/fileUpload").order(Integer.MIN_VALUE);
    }
}