【问题标题】:Cannot use Apache Commons FileUpload with Spring Boot multipart.resolve-lazily无法将 Apache Commons FileUpload 与 Spring Boot multipart.resolve-lazily 一起使用
【发布时间】:2023-04-05 18:28:02
【问题描述】:

我正在使用 Spring Boot 框架构建一个 REST API。有一个端点,用户可以上传一个大文件(~1GB)。我正在使用来自 Apache Commons FileUpload 的 Streaming API

我只想在该端点启用流式传输。因此,我将我的 Spring Boot 配置如下:

spring.servlet.multipart.enabled = true
spring.servlet.multipart.resolve-lazily = true
spring.servlet.multipart.max-file-size = 2GB
spring.servlet.multipart.max-request-size = 2GB

这是我的终点:

@PostMapping(path = "/import", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<String> importData(HttpServletRequest request) throws IOException, FileUploadException {
    System.out.println("Streaming...");

    boolean isMultipart = ServletFileUpload.isMultipartContent(request);
    if (!isMultipart) {
        return ResponseEntity.badRequest().build();
    }

    ServletFileUpload upload = new ServletFileUpload();
    FileItemIterator iterStream = upload.getItemIterator(request);
    while (iterStream.hasNext()) {
        System.out.println("Iterating...");

        FileItemStream item = iterStream.next();

        if (!item.isFormField()) {

            String name = item.getFieldName();
            System.out.println("Field name is: " + name);

            try (InputStream uploadedStream = item.openStream();
                 OutputStream out = new FileOutputStream("file.zip")) {

                IOUtils.copy(uploadedStream, out);
            }

        } else {

            try (InputStream stream = item.openStream()) {
                String formFieldName = item.getFieldName();
                String formFieldValue = Streams.asString(stream);
                System.out.println(String.format("Form field found - %s: %s", formFieldName, formFieldValue));
            }
        }
    }

    return ResponseEntity.ok("Data streamed successfully.");
}

调用方法并执行代码。但是,FileItemIterator 是空的,那里的while 循环没有被执行。

如果我设置spring.servlet.multipart.enabled = false,此代码将完美运行。但我不想这样做,因为正如我所说,我不想全局禁用 Spring Boot Multipart Resolver,但只能在这个端点上。

那么,我的代码有什么问题?为什么FileItemIterator 是空的?

感谢您的帮助。

【问题讨论】:

    标签: java spring spring-boot streaming apache-commons-fileupload


    【解决方案1】:

    我解决了我的问题。

    我认为问题出在 Spring StandardServletMultipartResolver。当我切换到CommonsMultipartResolver(如下配置)时,我的代码运行良好。

    @Bean(name = "multipartResolver")
    public CommonsMultipartResolver multipartResolver() {
        CommonsMultipartResolver resolver = new CommonsMultipartResolver();
        resolver.setDefaultEncoding("UTF-8");
        resolver.setResolveLazily(true);
        return resolver;
    }
    

    【讨论】:

    • 您好,感谢您的回答。不幸的是,它并没有为我解决问题。 iterStream.hasNext() 从一开始就返回 false。我正在使用一些拦截器和 Spring Security,它们可能会在请求到达我的控制器之前弄乱请求。就您而言,您是否还有 Spring Security 和例如正在使用 LocaleChangeInterceptor?提前致谢。
    • 嗨,我有 Spring Security 但没有拦截器。
    • 好的,我可以确认通过禁用拦截器,hasNext() 已经开始返回 true。感谢您的反馈。
    • 要禁用特定 URL 的拦截器,请执行以下操作: @Override public void addInterceptors(final InterceptorRegistry registry) { registry.addInterceptor(localeChangeInterceptor()).addPathPatterns("/**").excludePathPatterns ("/the/endpoint/you/use/for/upload"); }
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-21
    • 1970-01-01
    • 2020-03-09
    • 2010-11-09
    • 1970-01-01
    • 2018-08-27
    • 1970-01-01
    相关资源
    最近更新 更多