3

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

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

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

1. application.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");
    }
}

但每次我得到同样的例外。

4

2 回答 2

3

除了评论之外,我可能会建议创建一个@Beanfor FactoryMultipartConfigurationElement 如果您有来自 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

于 2020-03-06T14:33:35.993 回答
0

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

  1. 在 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>
    
  2. 从 yml 中删除:

    sprint:
      servlet:  
        multipart:
          enabled: true
          file-size-threshold: 2KB
          max-file-size: 10MB
          max-request-size: 10MB
    
  3. 添加到 yml:

    server:
      tomcat:
        max-swallow-size: -1
        max-http-form-post-size: -1
    
  4. 最后但并非最不重要:

    @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;
    }
    
于 2021-10-01T12:33:47.193 回答