如何使用嵌入式 tomcat 在 Spring Boot 中增加文件大小上传限制

Posted

技术标签:

【中文标题】如何使用嵌入式 tomcat 在 Spring Boot 中增加文件大小上传限制【英文标题】:How to increase file size upload limit in spring boot using embedded tomcat 【发布时间】:2020-06-19 05:47:07 【问题描述】:

我正在尝试使用我的 Spring Boot API 上传文件。当我使用小文件(小于 1 MB)时,该功能工作正常,但是当我上传大文件时,它给了我一个异常。我正在使用嵌入式 Tomcat 服务器。

“超出最大上传大小;嵌套异常是 java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException: 字段文件超出了其最大允许大小 1048576 字节。”

我在我的文件中尝试了以下代码,但每次我都收到错误

1.应用程序.property

server.tomcat.max-swallow-size=100MB

server.tomcat.max-http-post-size=100MB

spring.servlet.multipart.enabled=true

spring.servlet.multipart.fileSizeThreshold=100MB

spring.servlet.multipart.max-file-size=100MB

spring.servlet.multipart.max-request-size=100MB

我也试过了

spring.servlet.multipart.maxFileSize=100MB

spring.servlet.multipart.maxRequestSize=100MB

2。爱人是我的文件上传代码

public RestDTO uploadFile(MultipartFile file, String subPath) 

    if (file.isEmpty()) 
        return new RestFailure("Failed to store empty file");
    

    try 
        String fileName = new Date().getTime() + "_" + file.getOriginalFilename();
        String filePath = uploadPath + subPath + fileName;
        if (Objects.equals(file.getOriginalFilename(), "blob")) 
            filePath += ".png";
            fileName += ".png";
        
        File uploadDir = new File(uploadPath + subPath);
        if (!uploadDir.exists()) 
            uploadDir.mkdirs();
        
        FileOutputStream output = new FileOutputStream(filePath);
        output.write(file.getBytes());
        LOGGER.info("File path : " + filePath);

        MediaInfoDTO mediaInfoDTO = getThumbnailFromVideo(subPath, fileName);

        String convertedFileName = convertVideoToMP4(subPath, fileName);

        System.out.println("---------------->" + convertedFileName);

        return new RestData<>(new MediaDetailDTO(mediaInfoDTO.getMediaPath(), convertedFileName,
                mediaInfoDTO.getMediaType(), mediaInfoDTO.getMediaCodec(), mediaInfoDTO.getWidth(),
                mediaInfoDTO.getHeight(), mediaInfoDTO.getDuration()));
     catch (IOException e) 
        LOGGER.info("Can't upload file: " + e.getMessage());
        return new RestFailure("Failed to store empty file");
    

但每次我都遇到同样的异常。

【问题讨论】:

你使用的是哪个版本的 Spring Boot 我使用的是spring boot 2.1.7 spring.servlet.multipart.max-file-sizespring.servlet.multipart.max-request-size 仅适用于 Spring Boot 2.1.7。尝试将它们都设置为 -1(基本上无限制) 我使用了 spring.servlet.multipart.max-file-size=-1 和 spring.servlet.multipart.max-request-size=-1。还是不行 用正确的字节大小更新答案 【参考方案1】:

除了评论,我还可以建议为 Factory MultipartConfigurationElement 创建一个 @Bean 如果您有来自 TomCat 方面的任何限制,这基本上应该覆盖其他限制。

@Bean
public MultipartConfigElement multipartConfigElement() 
    MultipartConfigFactory factory = new MultipartConfigFactory();
    factory.setMaxFileSize(DataSize.ofBytes(100000000L));
    factory.setMaxRequestSize(DataSize.ofBytes(100000000L));
    return factory.createMultipartConfig();

这里DataSize的类型是org.springframework.util.unit.DataSize

参考https://github.com/spring-projects/spring-boot/issues/11284

我怀疑另一个问题可能来自 TomCat maxSwallowSize 如果上述方法不起作用,请参阅 Baeldung 的第 5 点。 https://www.baeldung.com/spring-maxuploadsizeexceeded

【讨论】:

没有必要这样做。 Spring Boot 将使用spring.servlet.multipart.* 属性自动配置MultipartConfigElement【参考方案2】:

在查看了许多示例并进行了多次测试但没有结果之后。我已经设法通过以下配置解决了这个问题:

    在 pom 中添加以下依赖项:

    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.4</version>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.6</version>
    </dependency>
    

    从 yml 中删除:

    sprint:
      servlet:  
        multipart:
          enabled: true
          file-size-threshold: 2KB
          max-file-size: 10MB
          max-request-size: 10MB
    

    添加到 yml:

    server:
      tomcat:
        max-swallow-size: -1
        max-http-form-post-size: -1
    

    最后但同样重要的是:

    @Bean
    public MultipartResolver multipartResolver() 
        CommonsMultipartResolver resolver
           = new CommonsMultipartResolver();
        resolver.setDefaultEncoding(StandardCharsets.UTF_8.displayName());
        resolver.setMaxUploadSize(52428800L); //50MB
        resolver.setMaxUploadSizePerFile(52428800L); //50MB
    
        return resolver;
    
    
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public ResponseEntity<Object> handleFileUploadError(MaxUploadSizeExceededException ex) 
        return ResponseEntity.status(EXPECTATION_FAILED).body(
            CustomResponse.builder()
                .status(Status.ERROR)
                .message(ex.getMessage())
                .build());
    
    
    // Where CustomResponse class is in my case:
    /**
      * The UploadResponse class
      * <p>
      * Contain the response body
      */
    @Getter
    @Builder(toBuilder = true)
    @AllArgsConstructor
    @JsonInclude(JsonInclude.Include.NON_NULL)
    public class CustomResponse 
        /**
          * The status
          */
        private final Status status;
        /**
          * The message
          */
        private final String message;
        /**
          * The errors
          */
        private final Set<String> errors;
    
    

【讨论】:

自定义异常处理程序很好,否则你会得到一个丑陋的500 Internal Server 错误,这是由 Sprint 的默认异常处理程序提供的。但是,要增加文件大小限制,我所要做的就是将spring.servlet.multipart.max-file-size=10485760 添加到我的application.properties。无需创建自定义 MultipartResolver bean。

以上是关于如何使用嵌入式 tomcat 在 Spring Boot 中增加文件大小上传限制的主要内容,如果未能解决你的问题,请参考以下文章