上传文件超过最大限制时无法捕获异常

概述

本文记录一个使用Spring (Boot)上传文件时遇到的异常无法捕获的问题。

背景

最近在做一个视频检测需求,考虑到阿里云OSS空间和网络带宽限制,对于客户端提交的视频文件有大小限制,信息配置在文件application.yml

spring:
  servlet:
    multipart:
      enabled: true
      max-file-size: 100MB
      max-request-size: 100MB

然后使用postman上传一个文件加以测试,响应报错信息为:
在这里插入图片描述
未知异常?一练懵逼。

排查

好在IDEA 控制台(当然,在本地*-error.log日志文件中也有记录)记录报错为:

com.central.common.exception.DefaultExceptionAdvice 未知异常
org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size exceeded; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException: The field file exceeds its maximum permitted size of 10485760 bytes.

这个报错信息太不友好,导致一开始可能不知道从哪里去排查。

想到未知异常这几个字的报错信息源头是DefaultExceptionAdvice:

@Slf4j
@ResponseBody
public class DefaultExceptionAdvice {
    /**
     * IllegalArgumentException异常处理返回json
     * 返回状态码:400
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler({IllegalArgumentException.class})
    public Result badRequestException(IllegalArgumentException e) {
        return defHandler("参数解析失败", e);
    }

    /**
     * AccessDeniedException异常处理返回json
     * 返回状态码:403
     */
    @ResponseStatus(HttpStatus.FORBIDDEN)
    @ExceptionHandler({AccessDeniedException.class})
    public Result badMethodExpressException(AccessDeniedException e) {
        return defHandler("没有权限请求当前方法", e);
    }

    /**
     * 返回状态码:405
     */
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    public Result handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        return defHandler("不支持当前请求方法", e);
    }

    /**
     * 返回状态码:415
     */
    @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
    @ExceptionHandler({HttpMediaTypeNotSupportedException.class})
    public Result handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {
        return defHandler("不支持当前媒体类型", e);
    }

    /**
     * SQLException sql异常处理
     * 返回状态码:500
     */
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler({SQLException.class})
    public Result handleSQLException(SQLException e) {
        return defHandler("服务运行SQLException异常", e);
    }

    /**
     * BusinessException 业务异常处理
     * 返回状态码:500
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(BusinessException.class)
    public Result handleException(BusinessException e) {
        return defHandler(e.getMessage(), e);
    }

    /**
     * 所有异常统一处理
     * 返回状态码:500
     */
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(Exception.class)
    public Result handleException(Exception e) {
        return defHandler("未知异常", e);
    }

    private Result defHandler(String msg, Exception e) {
        log.error(msg, e);
        return Result.failed(msg);
    }
}

不用分析,不难得知上面代码里啰嗦且冗余的诸多方法定义用于不同类型的Exception。这里面并没有我们在前面提到的MaxUploadSizeExceededException异常,那新增一个方法用于捕获此异常并返回业务场景错误响应体:

@ControllerAdvice
public class ExceptionAdvice extends DefaultExceptionAdvice {
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    @ResponseBody
    public String exception(MaxUploadSizeExceededException e) {
        // return e.getLocalizedMessage();
        return "上传文件最大不可超过100M";
    }
}

此时报错响应信息效果:
在这里插入图片描述
实现预期效果!

插曲

我们再来看看报错信息:

org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size exceeded; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException: The field file exceeds its maximum permitted size of 10485760 bytes.

一开始看到FileSizeLimitExceededException,试图用ExceptionHandler捕获FileSizeLimitExceededException

@ExceptionHandler(FileSizeLimitExceededException.class)
@ResponseBody
public String exception(SizeLimitExceededException e) {
	return e.getLocalizedMessage();     
}

结果并不能捕获。FileSizeLimitExceededException是tomcat-embed-core依赖包里面定义的异常。

后来切换成MaxUploadSizeExceededException,捕获成功。

看一下其他异常捕获方法:

@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public List<ErrorMsg> exception(MethodArgumentNotValidException e) {
}

MethodArgumentNotValidException可以捕获异常。

总结

一个没有得到理论支持的结果
在使用ControllerAdvice和ExceptionHandler捕获异常时,只能捕获org.springframework.web下面的异常,即在下面依赖里面有定义的异常:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
</dependency>

参考

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

johnny233

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值