Spring Boot 句柄 SizeLimitExceededException

Nab*_*bor 4 java 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;
                }
            }
        }
Run Code Online (Sandbox Code Playgroud)

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

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

gly*_*ing 5

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

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

这应该允许您专注于“最大文件大小”异常,而不必进入 servlet 容器细节。

更新 1以回应此评论:

听起来不错,SizeLimitExceededException 提供的 getPermittedSize 和 getActualSize 怎么样,不仅在使用 Tomcat 时,还有机会获得这些值吗?

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

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