前端反馈上传过大的文件,没有返回存储信息。
一、场景说明
我这里是springCloud2020.0.2+springBoot2.4.5,spring原生微服务,没有依赖第三方的组件。容器用的是undertow,这里先说下用这个容器有一个坑,后面说。
二、配置情况
我这里是配了:
1、配置了openFeign的传参限制

#feign配置
feign:
  httpclient:
    connection-timeout: 30000
#请求压缩
  compression:
    request:
      enabled: true
      min-request-size: 2048
    response:
      enabled: true
      max-request-size: 204800000
2、配置了上传文件的大小限制
#设置时间格式
spring:
#文件上传配置
  servlet:
    multipart:
      enabled: true # 是否支持多部分上传。
      maxFileSize: 20MB # 最大支持文件上传的大小
      maxRequestSize: 200MB # 支持请求最大文件上传的大小
3、配置了容器的http请求的传参限制
#容器中间件undertow配置
server:
  shutdown: graceful    # 优雅停机
  undertow:
    accesslog:
      dir: logs
      enabled: false
    buffer-size: 1024
    direct-buffers: true
    max-http-post-size: -1B
    threads:
      io: 8
      worker: 256

设置为-1B表示不限制
三、统一异常处理类

package com.fillersmart.fsihouse.thirdweb.exception;

import com.fillersmart.fsihouse.data.common.api.ResponseCodeI18n;
import com.fillersmart.fsihouse.data.core.Result;
import com.fillersmart.fsihouse.data.core.ResultGenerator;
import io.undertow.server.handlers.form.MultiPartParserDefinition;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileUploadBase;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MultipartException;

/**
 * 第三方服务接口层统一异常处理
 *
 * @author zhengwen
 **/
@Slf4j
@RestControllerAdvice
public class GloabExceptionHandler {
    /**
     * 处理文件上传大小超限制
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(value = MultipartException.class)
    public Result<?> fileUploadExceptionHandler(MultipartException exception) {
        Throwable throwable = exception.getRootCause();
        if (throwable instanceof FileUploadBase.FileSizeLimitExceededException) {
            log.error("上传文件过大", exception);
            return ResultGenerator.genFailResult(ResponseCodeI18n.UPLOAD_FILE_ALONE_GT_MAX_SIZE.getMsg());
        }
        if (throwable instanceof FileUploadBase.SizeLimitExceededException) {
            log.error("总上传文件过大", exception);
            return ResultGenerator.genFailResult(ResponseCodeI18n.UPLOAD_FILE_GT_TOTAL_MAX_SIZE.getMsg());
        }
        //容器undertow文件上传过大异常支持
        if (throwable instanceof MultiPartParserDefinition.FileTooLargeException) {
            log.error("上传文件过大", exception);
            return ResultGenerator.genFailResult(ResponseCodeI18n.UPLOAD_FILE_ALONE_GT_MAX_SIZE.getMsg());
        }
        log.error("上传文件异常", exception);
        return ResultGenerator.genFailResult(ResponseCodeI18n.UPLOAD_FILE_EXCEPTION.getMsg());
    }

}

这里使用spring3.2开始提供的新注解@RestControllerAdvice配合@ExceptionHandler注解,对@RestControllerAdvice注解使用详解感兴趣的,可以自行学习,这里不展开讲。
上面有注释的FileTooLargeException异常判断就是对undertow容器的支持,不然,容器会抛出异常:io.undertow.server.handlers.form.MultiPartParserDefinition$FileTooLargeException: UT000054: The maximum size 20971520 for an individual file in a multipart request was exceeded。不会被springMVC的异常拦截机制catch到,这应该是容器的问题,如果用tomcat容器就没有这个问题。
最后说下我这个异常处理类所在的服务,我这个异常处理在接口层,也就网关转发的第一层。本来最开始我想把这个统一处理类直接放到网关层的,考虑到实际情况:
第一我放了后没有成功
原因:接口层没有继续往上throw异常。
第二考虑到后面其他平台可能有交互不走我们的网关,
所以最终就放在了接口层,向上返回的组织成我们内部用统一封装对象,其实里面就是一个code、msg、data。
网上之前百度了都说是undertow的问题,但是没有给出解决方案,建议不要用undertow,但是undertow的性能优势在那里,我不想抛弃,所以硬着头皮跟,最后找到了这个办法,其实看到控制台打印的异常,也是可以直接就处理了。希望可以帮到大家。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐