SpringBoot:当文件上传大小超过限制时,得到的是 MultipartException 而不是 MaxUploadSizeExceededException

17

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

我已配置 multipart.max-file-size=2MB,它可以正常工作。 但是,当我尝试上传超过2 MB大小的文件时,我希望处理该错误并显示错误消息。

为此,我让我的控制器实现了HandlerExceptionResolver,并实现了resolveException() 方法如下:

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);
    }
问题是我得到的异常是 MultipartException 而不是 MaxUploadSizeExceededException。
堆栈跟踪是: 无法解析多部分servlet请求;嵌套异常是 java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException:字段 myFile 超过其最大允许大小 2097152 字节。
在文件大小超过的情况下,为什么我没有得到 MaxUploadSizeExceededException?我得到了它的父异常 MultipartException,它可能发生在文件大小超过之外的许多其他原因。
对此有什么想法吗?
3个回答

7

我曾经遇到了同样的问题,看起来只有Commons File Upload实现的MultipartResolver会抛出MaxUploadSizeExceededException异常,而不是Servlet 3.0实现的MultipartResolver。

以下是我目前所做的事情。关键在于允许文件检查控制器,然后您可以验证大小并设置错误。

  1. 设置以下多部分属性 multipart: max-file-size: -1 max-request-size: -1

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

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

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


这是对我最有效的方法 - 感谢aalmero! - simbro

3

虽然不是很完美,但我快速而粗略的解决方案是检查MultipartException消息字符串是否包含文本SizeLimitExceededException,并从该消息中提取最大文件大小信息。

在我的情况下,在tomcat 8.0.x上抛出的异常是org.apache.tomcat.util.http.fileupload.FileUploadBase $ SizeLimitExceededException:请求被拒绝,因为其大小(177351)超过了配置的最大值(2048)

请记住,正如aalmero所指出的,如果您使用的是CommonsMultipartResolver而不是StandardServletMultipartResolver,则会抛出MaxUploadSizeExceededException,这样处理起来会更容易。以下代码处理由任一多部分解析器策略引发的MultipartException

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

  // https://dev59.com/33A75IYBdhLWcg3wfpKr#5599842
  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];
  }
}

1
以下的application.properties值适用于我。看起来它使文件大小无限制可接受。
multipart.maxFileSize=-1

multipart.maxRequestSize=-1

现在您需要在控制器端添加逻辑。
@PostMapping("/upload")
    public String handleFileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) {

        long size = file.getSize();

        if(size > 10000000)
        {
            redirectAttributes.addFlashAttribute("message",
                    "You file " + file.getOriginalFilename() + "! has not been successfully uploaded. Requires less than 10 MB size.");
            return "redirect:/upload";
        }
        }

1
这篇回答似乎并没有回答问题,问题是关于如何在上传大文件时捕获异常,而不是如何上传任意大小的文件。 - Robert Longson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接