SpringBoot当文件上传大小限制超过获取MultipartException而不是MaxUploadSizeExceededException

Posted

技术标签:

【中文标题】SpringBoot当文件上传大小限制超过获取MultipartException而不是MaxUploadSizeExceededException【英文标题】:SpringBoot When file upload size limit exceeds getting MultipartException instead of MaxUploadSizeExceededException 【发布时间】:2016-05-24 14:45:23 【问题描述】:

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

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

为此,我的控制器实现了 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);
    

问题是我得到的异常是 MultipartException 而不是 MaxUploadSizeExceededException

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

在文件大小超过的情况下,为什么我没有得到 MaxUploadSizeExceededException?我得到它的父异常 MultipartException 除了文件大小超出之外,还有许多其他原因。

对此有什么想法吗?

【问题讨论】:

【参考方案1】:

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

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

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

    设置 Tomcat 8 (maxSwallowSize="-1")

    在控制器上,添加逻辑来检查大小

    if(fileAttachment.getSize() > 10485760) 抛出新的 MaxUploadSizeExceededException(fileAttachment.getSize());

【讨论】:

这是最适合我的方法 - 感谢 aalmero!【参考方案2】:

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";
        
        

【讨论】:

这似乎没有回答所写的问题,即关于如何在上传大文件时捕获异常,而不是关于如何上传任意大小的文件。【参考方案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;
  

  // http://***.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];
  

【讨论】:

以上是关于SpringBoot当文件上传大小限制超过获取MultipartException而不是MaxUploadSizeExceededException的主要内容,如果未能解决你的问题,请参考以下文章

springboot调整上传文件大小限制

SpringBoot tomcat 上传文件大小受限制

iview实现文件上传 限制上传格式大小

SpringBoot上传文件大小设置

Laravel - 超过 PHP 最大上传大小限制时验证文件大小

怎么在js 里面限制上传图片的大小不能超过 1M?