一尘不染

Spring Boot句柄SizeLimitExceededException

spring-boot

我使用Spring Boot 1.5.7。
我没有配置CommonsMultipartResolver,因为Spring Boot已经可以处理文件上传了。

如果我的上传内容超出了允许的最大大小,则会引发难看的异常。
这由我的控制器处理。

@ControllerAdvice
public abstract class DefaultController implements InitializingBean {
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ServiceException> handleException(final Exception ex) {
        ...
        } else if (ex instanceof MultipartException) {
            MultipartException me = (MultipartException) ex;
            Throwable cause = ex.getCause();
            if (cause instanceof IllegalStateException) {
                Throwable cause2 = cause.getCause();
                if (cause2 instanceof SizeLimitExceededException) {
                    // this is tomcat specific
                    SizeLimitExceededException slee = (SizeLimitExceededException) cause2;
                }
            }
        }

这种处理不仅复杂,而且可悲的是特定于Tomcat,因为SizeLimitExceededException在软件包中org.apache.tomcat.util.http.fileupload.FileUploadBase

我该如何处理这种错误情况,即不管使用哪个Servlet引擎,有人上传一个更大的文件然后被允许并返回一条漂亮的消息?


阅读 616

收藏
2020-05-30

共1个答案

一尘不染

您可以在@ControllerAdvice其中定义专门用于的异常处理程序方法MultipartException,然后使用特定的限定它HttpStatus。例如:

@ExceptionHandler(MultipartException.class)
@ResponseStatus(value = HttpStatus.PAYLOAD_TOO_LARGE)
public ResponseEntity<ServiceException> handleMultipartException(MultipartException ex) {
    ...
}

这应该使您可以专注于“最大文件大小”异常,而不必深入了解servlet容器的细节。

更新1 以回应此评论:

听起来不错,由SizeLimitExceededException提供的getPermittedSize和getActualSize怎么办?不仅使用Tomcat,还有机会获得此值吗?

通过基于(a)异常类型和(b)HTTP状态截获此错误,您可以使该解决方案普遍适用。但是这样做可能会丢失一个servlet容器(但可能不是另一个)可能给您的那种详细信息。您可以通过设置spring.http.multipart.max- file-size在这种情况下可以报告“允许的大小”来实施自己的最大大小,但是如果要报告“实际大小”,则必须考虑以下其中一项:

  • 必须使用servlet容器提供的东西
  • 选择一个spring.http.multipart.max-file-size小于servlet容器支持的最大值的值,然后在控制器内部应用自己的max size检查,并抛出包含实际和允许大小的特定异常类型。
2020-05-30