Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot handle SizeLimitExceededException

I use Spring boot 1.5.7.
I have not configured CommonsMultipartResolver, because Spring Boot handles file uploads already.

If my upload exceeds the maximum permited size, an ugly Exception is thrown.
This is handled by my controller.

@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;
                }
            }
        }

This kind of handling is not only complex but also sadly Tomcat specific, because the SizeLimitExceededException is in the package org.apache.tomcat.util.http.fileupload.FileUploadBase.

How can I handle the error case, that some one uploads a bigger file then allowed and return a nice message, regardless which Servlet Engine is used?

like image 639
Nabor Avatar asked Oct 12 '17 11:10

Nabor


2 Answers

You could define a exception handler method in your @ControllerAdvice which is specifically for MultipartException and then qualify it with a specific HttpStatus. For example:

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

This should allow you to focus on the 'maximum file size' exception without having to get into servlet container specifics.

Update 1 in response to this comment:

Sounds good, what about getPermittedSize and getActualSize provided by SizeLimitExceededException is there a chance to get this values not only if Tomcat is used?

By intercepting this error on the basis of (a) the exception type and (b) the HTTP status ... you are making the solution generally applicable. But in so doing you might lose the sort of detailed information that one servlet container (but perhaps not another) might give you. You could perhaps enforce your own maximum size by setting spring.http.multipart.max-file-size in which case you would be able to report 'permitted size' but if you want to report 'actual size' then you'll have to consider one of the following:

  • Have to use something provided by the servlet container
  • Choose a spring.http.multipart.max-file-size which is less thatn the supported maximum for your servlet container and then apply your own max size check inside your controller and throw your own specific exception type containing the actual and permitted sizes.
like image 170
glytching Avatar answered Oct 26 '22 18:10

glytching


This working fine in my @RestControllerAdvice and the exception is more specific than MultipartException :

@ExceptionHandler(MaxUploadSizeExceededException.class)
@ResponseStatus(value = HttpStatus.PAYLOAD_TOO_LARGE)
public ResponseEntity handleMultipartException(MaxUploadSizeExceededException e) {

    Map<String, String> result = new HashMap<>();
    result.put("message", "Error ==> Large File ");
    return  ResponseEntity.status(HttpStatus.PAYLOAD_TOO_LARGE)
            .body(result);

}

PS : when using @RestControllerAdvice(annotations = RestController.class) it doens't work .. you have to put @RestControllerAdvice without RestController.class annotation

like image 1
Saad Joudi Avatar answered Oct 26 '22 19:10

Saad Joudi