SpringBoot 当文件上载大小限制超过获取 MultipartException 而不是 MaxUploadSizeExceedException 时

2022-09-03 07:40:22

我有简单的SpringBoot应用程序文件上传功能,其中最大文件上传文件大小为2 MB。

我已经配置了它工作正常。但是,当我尝试上传大于2 MB的文件时,我想处理该错误并显示错误消息。multipart.max-file-size=2MB

为此,我有我的控制器实现,实现如下:HandlerExceptionResolverresolveException()

public ModelAndView resolveException(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception exception)
    {        
        Map<String, Object> model = new HashMap<String, Object>();
        if (exception instanceof MaxUploadSizeExceededException)
        {
            model.put("msg", exception.getMessage());
        } else
        {
            model.put("msg", "Unexpected error: " + exception.getMessage());
        }

        return new ModelAndView("homepage", model);
    }

问题是异常 Im 获取的是 MultipartException 而不是 MaxUploadSizeExceedException

堆栈跟踪是:无法解析多部分 servlet 请求;嵌套异常是 java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUpload.FileUploadBase$FileSizeLimitExceedException:字段 myFile 超过其允许的最大大小2097152 字节。

在文件大小超过的情况下,为什么我没有得到MaxUploadSizeExceedException?我得到它的父异常多部分异常,除了文件大小超过之外,还可以由于许多其他原因而发生。

对此有什么想法吗?


答案 1

我遇到了同样的问题,看起来只有Commons File Upload的MultipartResolver实现了MaxUploadSizeExceedException,而不是MultipartResolver Servlet 3.0实现。

以下是我到目前为止所做的工作。这里的关键是允许在控制器上检查文件,然后您可以验证大小并设置错误。

  1. 在多部分以下设置多部分属性:最大文件大小:-1 最大请求大小:-1

  2. 设置 Tomcat 8 (maxSwallowSize=“-1”)

  3. 在控制器上,添加逻辑以检查大小

    if(fileAttachment.getSize() > 10485760 ) { throw new MaxUploadSizeExceedException(fileAttachment.getSize()); }


答案 2

这不是很好,但我的快速和肮脏的解决方案是检查消息字符串是否包含文本,并从该消息中提取最大文件大小信息。MultipartExceptionSizeLimitExceededException

在我的例子中,tomcat 8.0.x上引发的异常是org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceedException:请求被拒绝,因为它的大小(177351)超过了配置的最大值(2048)

请记住,正如 aalmero 所指出的,如果你使用 而不是 ,a 将被抛出,这样处理起来会好得多。以下代码处理由任一多部分解析器引发的策略:CommonsMultipartResolverStandardServletMultipartResolverMaxUploadSizeExceededExceptionMultipartException

@ControllerAdvice
public class MultipartExceptionExceptionHandler {
  @ExceptionHandler(MultipartException.class)
  public String handleMultipartException(MultipartException ex, RedirectAttributes ra) {
    String maxFileSize = getMaxUploadFileSize(ex);
    if (maxFileSize != null) {
      ra.addFlashAttribute("errors", "Uploaded file is too large.  File size cannot exceed " + maxFileSize + ".");
    }
    else {
      ra.addFlashAttribute("errors", ex.getMessage());
    }
    return "redirect:/";
  }

  private String getMaxUploadFileSize(MultipartException ex) {
    if (ex instanceof MaxUploadSizeExceededException) {
      return asReadableFileSize(((MaxUploadSizeExceededException)ex).getMaxUploadSize());
    }
    String msg = ex.getMessage();
    if (msg.contains("SizeLimitExceededException")) {
      String maxFileSize = msg.substring(msg.indexOf("maximum")).replaceAll("\\D+", "");
      if (StringUtils.isNumeric(maxFileSize)) {
        return asReadableFileSize(Long.valueOf(maxFileSize));
      }
    }

    return null;
  }

  // http://stackoverflow.com/a/5599842/225217
  private static String asReadableFileSize(long size) {
    if(size <= 0) return "0";
    final String[] units = new String[] { "B", "kB", "MB", "GB", "TB" };
    int digitGroups = (int) (Math.log10(size)/Math.log10(1024));
    return new DecimalFormat("#,##0.#").format(size/Math.pow(1024, digitGroups)) + " " + units[digitGroups];
  }
}

推荐