经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Spring Boot » 查看文章
spring boot上传文件超出大小异常无法捕获问题
来源:w3xue  时间:2019/10/12 16:17:50  对本文有异议

我们使用Spring Boot上传功能的时候,会遇到文件大小超出限制的问题。Tomcat默认的大小是1M。因此,我们首先应该修改这个限制。我们在配置文件application.propertiesapplication.yml上修改上传文件大小限制即可。下面是application.properties的语法

  1. spring.servlet.multipart.max-file-size=5MB
  2. spring.servlet.multipart.max-request-size=10MB

application.yml放在spring 大节下面:

  1. servlet:
  2.   multipart:
  3.     max-file-size: 5MB
  4.     max-request-size: 10MB

第一个是文件大小限制,第二个是总响应大小限制。

但我们设置后,如果有大于5M的文件上传,还是会抛出异常,且这个异常,在Controller层是catch不到的,因为如果文件超限,在进controller之前,异常已经被抛出了。如何解决这个问题呢?

方式一:

增加异常捕获类

  1. @RestControllerAdvice
  2. public class MyExceptionHandler {
  3.         /* spring默认上传大小1MB 超出大小捕获异常MaxUploadSizeExceededException */
  4.     @ExceptionHandler(MaxUploadSizeExceededException.class)
  5.     public Map handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) {
  6.         return Map.of("code", 500, "msg", "文件大小超出5MB限制, 请压缩或降低文件质量! ");
  7.     }
  8. }

或者 

  1.  @RestControllerAdvice
  2. public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
  3.  private static final Logger logger = 
  4.     LoggerFactory.getLogger(GlobalExceptionHandler.class);
  5.  
  6.  /**
  7.      * 处理上传异常
  8.      * @param t
  9.      * @return
  10.      */
  11.     @ExceptionHandler(MultipartException.class)
  12.     public ResponseEntity<Result> handleAll(Throwable t) throws Exception {
  13.         // TODO do Throwable t
  14.         logger.error("=>"+t.getMessage());
  15.         HttpHeaders headers = new HttpHeaders();
  16.         headers.set("Content-Type","application/json;charset=UTF-8");
  17.         return new ResponseEntity<>(new Result(-1,"上传文件异常!",null),headers, HttpStatus.OK);
  18.     }

此处注意使用

  1. @RestControllerAdvice

而不能

  1. @ControllerAdvice(
  2.     annotations = {RestController.class}
  3. )

方式二:

文件大小的校验是在controller之前的,可以通过继承CommonsMultipartResolver类,覆盖parseRequest方法,捕获异常后自己处理 

在使用Spring Security时,CommonsMultipartResolver不会作为“multipartResolver”bean添加,而是作为“filterMultipartResolver”:

  1. @Bean(name="filterMultipartResolver")
  2. CommonsMultipartResolver filterMultipartResolver() {
  3.     CommonsMultipartResolver filterMultipartResolver = new CommonsMultipartResolver();
  4.     filterMultipartResolver.setMaxUploadSize(MAXSIZE);
  5.     return filterMultipartResolver;
  6. }

如果我设置filterMultipartResolver.setResolveLazily(true);没什么区别.

如果我用自己的子类化CommonsMultipartResolver,并用捕获MaxUploadSizeExceededException并返回一个空的MultipartParsingResult的东西来覆盖parseRequest()方法,我会得到一个“403 Forbidden”错误:

  1. public class ExtendedCommonsMultipartResolver extends CommonsMultipartResolver {
  2.     protected MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException {
  3.         String encoding = determineEncoding(request);
  4.         try {
  5.             return super.parseRequest(request);
  6.         } catch (MaxUploadSizeExceededException e) {
  7.             return parseFileItems(Collections.<FileItem> emptyList(), encoding);
  8.         }
  9.     }
  10. }

最后,实现某种本地或全局的ExceptionHandler没有任何意义,因为它永远不会被调用. 

尝试使用@ControllerAdvice创建一个单独的类,这将处理来自所有控制器的异常。

  1. @ControllerAdvice 
  2. public class ExceptionControllerAdvice { 
  3.  
  4.     @ExceptionHandler(MaxUploadSizeExceededException.class) 
  5. public String handleException(MaxUploadSizeExceededException e, RedirectAttributes redirectAttributes) { 
  6.     redirectAttributes.addFlashAttribute("uploadErrorMessage", e.getCause().getMessage()); 
  7.     return "redirect:/page"; 
  8. } 
  9. }

因此,如果我们在@ControllerAdvice类中定义的方法上我们@ExceptionHandler注解,它将被应用到所有控制器。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号