多部分文件最大大小异常 - Spring Boot嵌入式Tomcat

11
我已将最大文件大小设置为
multipart.maxFileSize: 1mb
multipart.maxRequestSize: 1mb

这是我的控制器:
@RequestMapping(method=RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ResponseStatus(HttpStatus.CREATED)
@Secured(Privileges.CAN_USER_READ)
public void create(@RequestParam("file")final MultipartFile file,Principal principal) throws IllegalStateException, IOException,MultipartException{

    medicalHistoryService.create(new MedicalHistory(file));
}

这是错误消息

2016-03-03 13:48:24.560  WARN 4992 --- [nio-8080-exec-1] h.c.w.RestResponseEntityExceptionHandler : Could not parse multipart servlet request; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (9288401) exceeds the configured maximum (1048576)

2016-03-03 13:48:25.545  WARN 4992 --- [nio-8080-exec-2] h.c.w.RestResponseEntityExceptionHandler : Could not parse multipart servlet request; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (9288401) exceeds the configured maximum (1048576)

请求过大的文件后的最终结果是页面加载问题。在堆栈跟踪中没有其他错误,所以我有点被卡住了,不知道实际发生了什么。噢,是的,我尝试了很多其他解决方案,比如注册过滤器,在ErrorController中处理异常。每次我最终都会得到同样的结果 - 服务器崩溃。

Tomcat crash

编辑 2

我的异常处理类:

@ControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler{

   // 413 MultipartException - file size too big 
@ExceptionHandler({MultipartException.class,FileSizeLimitExceededException.class,java.lang.IllegalStateException.class})
   public ResponseEntity<Object> handleSizeExceededException(final WebRequest request, final MultipartException ex) {
        //log.warn("413 Status Code. File size too large {}", ex.getMessage());
       log.warn(ex.getMessage());
       final ApiError apiError = message(HttpStatus.PAYLOAD_TOO_LARGE, ex);
       return handleExceptionInternal(ex, apiError, new HttpHeaders(), HttpStatus.PAYLOAD_TOO_LARGE, request);
   }
}

你还没有展示足够的代码。例如,handleExceptionInternal是做什么的?提供一个最小化、完整化、可验证化的示例将使人们更容易地帮助你。 - Andy Wilkinson
handleExceptionInternalResponseEntityExceptionHandler的内部方法,根据文档说明,它是一个方便的基类,用于提供集中式异常处理的{@link ControllerAdvice @ControllerAdvice}类。 - SeaBiscuit
7个回答

27

从Spring Boot 2开始

spring.servlet.multipart.max-file-size=128KB
spring.servlet.multipart.max-request-size=128KB

请参考文档

Spring Boot 1.x

属性应该像这样:
spring.http.multipart.max-file-size=128KB
spring.http.multipart.max-request-size=128KB

请参考Spring Boot指南


对我来说,这个答案解决了问题,而无需声明任何特定于Tomcat的bean。问题在于我使用了spring.servlet.multipart.max-file-size=128KB而不是spring.http... - Mate Šimović
1
这个不起作用,至少在Spring Boot 2.1.3中是这样的。这些属性已经不存在了,请查看:https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#common-application-properties - voliveira89
1
@voliveira89,非常感谢您的评论!我已经编辑了我的回答。 - jimmbraddock

12

这个有点棘手。Tomcat的MaxSwallowSize属性导致了这个问题。显然它是在最近的某个版本中引入的。整个想法背后的原因是,如果Tomcat意识到请求将被拒绝,就会终止连接,而默认值2mb以上的任何内容都会被终止(至少这是我的理解)。简单地覆盖此属性可以修复问题。我知道这不是完美的解决方案,但比仅仅终止连接要好得多。

@Bean
public TomcatEmbeddedServletContainerFactory containerFactory() {
    TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
     factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
        @Override
        public void customize(Connector connector) {
         ((AbstractHttp11Protocol<?>) connector.getProtocolHandler()).setMaxSwallowSize(-1);
        }
     });
     return factory;
}

你刚刚帮我避免了在问题中发布基本相同的代码。如果没有花费数小时的麻烦,我怀疑我是否能够发现答案,所以非常感谢你,谢谢你,谢谢你。 - Tim Perry
谢谢你,你做得很好,它应该成为Springboot文档的一部分。 - lekant
1
这不再是正确的解决方案,像@jimmbraddock所说的那样设置属性是有效的。 - S. Ktifa
2
我不同意S. Ktifa的观点。例外情况是:"org.apache.tomcat.util.http.fileupload.FileUploadBase$",所以我不相信你能够进入Spring,因此你必须调整一个bean来告诉Tomcat完成请求。更新了bean...一切都很顺利。你需要同时设置Spring和bean。 - Michael Cizmar
更正确的解决方案是使用应用程序属性 server.tomcat.max-swallow-size=-1 进行设置。 - user11153

5

请在 application.properties 中添加以下内容,适用于 Spring Boot 版本 - 2.0.1.RELEASE

spring.servlet.multipart.max-file-size=128MB
spring.servlet.multipart.max-request-size=128MB
spring.servlet.multipart.enabled=true

这解决了我的问题。

3

自从@SeaBiscuit提供了正确答案,但使用Spring boot 2.0.0.RELEASEorg.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory已被删除,并由类org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory替换。 因此,新的Spring boot 2.0.0代码将是:

  1. 创建一个带有任何名称的类并用@Configuration进行注释
  2. 将以下代码放入该类中
@Bean
public TomcatServletWebServerFactory containerFactory() {
    TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
    factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
        @Override
        public void customize(Connector connector) {
            ((AbstractHttp11Protocol<?>) connector.getProtocolHandler()).setMaxSwallowSize(-1);
        }
    });
    return factory;
}

如果您在配置Spring Boot 2.0.0中的最大文件上传大小时遇到问题,可以将以下代码放入“application.properties”文件中,并设置所需文件大小(以“MB”为单位):

## Image upload limitation properties
spring.servlet.multipart.max-file-size=3MB
spring.servlet.multipart.max-request-size=3MB

1

我尝试了上面所有的建议,但仍然遇到错误,直到我添加了这个:

  server.tomcat.max-swallow-size=-1

在application.properties文件中。

1
我在application.yml中写了几行代码来解决这个问题,例如:
spring:
    http:
        multipart:
            max-file-size: 10MB
            max-request-size: 10MB

但是这并没有解决问题。然而,将同样的行添加到格式化为单行方式的application.properties文件中,即属性文件方式,然后它就起作用了。


这篇文章并不是真正的回答问题。请注意,Stack Overflow 不像讨论论坛,它是一个问答网站,每个帖子都要么是问题,要么是回答问题。帖子也可以有评论 - 像这样的小句子 - 可以用来批评或要求作者澄清。这应该是一个评论或者新问题 - M.A.R.
我编辑了你的回答以删除问题,因为答案只应该提供答案。你可以将那个问题作为评论或新问题发布。 - Donald Duck
此配置已不建议使用,现在我们需要使用spring.servlet.multipart.max-file-size=10MB - Durgaprasad Kusuma

0
以下代码对我有效。将其添加到Spring Boot主类中:
import javax.servlet.MultipartConfigElement;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;



@SpringBootApplication
@EnableScheduling
@EnableAsync
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    
    @Bean
    MultipartConfigElement multipartConfigElement() {
        MultipartConfigFactory factory = new MultipartConfigFactory();
        factory.setMaxFileSize("5MB");
        factory.setMaxRequestSize("5MB");
        return factory.createMultipartConfig();
    }
}

来自审核:在 Stack Overflow 上,仅提供代码的答案是不被鼓励的,因为它们不解释它是如何解决问题的。请编辑您的答案以解释此代码的功能和如何回答问题,以使其对 OP 以及其他遇到类似问题的用户有用。请参见:如何编写一个好的答案?。谢谢 - sɐunıɔןɐqɐp

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