当前位置: 首页 > 知识库问答 >
问题:

无法让Spring启动延迟解析多部分文件

莘昊
2023-03-14

我已经用Spring Initializr创建了一个Spring Boot 2演示应用程序,并在下面添加了控制器:

@Controller
@RequestMapping("/demo")
public class UploadController {
    private final static Logger LOG = LoggerFactory.getLogger(UploadController.class);

    @PostMapping("/upload")
    public ResponseEntity<String> uploadFile(
        @RequestParam("metadata") MultipartFile metadata,
        @RequestParam("payload") MultipartFile payload) throws IOException {

        ObjectMapper mapper = new ObjectMapper();
        Map metadataMap = mapper.readValue(metadata.getInputStream(), Map.class);
        LOG.info("Received call to upload file {}", metadataMap.get("filename"));
        LOG.info("File size: {}", payload.getBytes().length);
        LOG.info("File {} successfully uploaded", metadataMap.get("filename"));

        return ResponseEntity.ok().build();
    }

}  

然后,我添加了一个包含此配置的应用程序.yaml 文件:

    spring:
      servlet:
        multipart:
          max-file-size: 2000000MB
          max-request-size: 2000000MB  
          resolve-lazily: true

我的目标是让控制器在开始读取< code>payload文件之前解析并记录< code>metadata文件,但是< code > resolve-lazyly 设置似乎被Boot忽略了:控制器内部的代码在整个主体被读取之前不会被执行。

我使用以下命令测试控制器:

curl-F元数据=@metadata。json-F payload=@payload。箱子http://localhost:8080/demo/upload

我的代码/配置有什么问题吗?我理解了这个设置的含义吗?

共有1个答案

楚瑞
2023-03-14

目前,如果你想避免一次读取(和缓冲)整个主体,我想你必须提供你自己的解析器,正如这里的答案所描述的。真正有趣的(但通常是不必要的)是以一种新的多解析器实现的形式来这样做。

对于接口MultipartResolver,有两个现有的实现文档,它们都提供了函数< code > setResolveLazily(boolean)(标准),(commons)。我已经尝试了这两种方法,但似乎都不允许单独解析或流式传输多部分文件或参数。

默认值为“false”,立即解析多部分元素,在解析多部分(javax.servlet.http.Http 请求)调用时引发相应的异常。对于延迟的多部分分析,将其切换为“true”,一旦应用程序尝试获取多部分文件或参数,就会引发分析异常。

尽管它在文档中说了什么,但我发现一旦你调用resoluteMultipart,整个身体就会在调用返回之前被解析和缓冲。我知道这一点,因为我可以观看正在创建的临时文件。

关于“我的代码有什么问题吗”的一个注释…

答:是的,因为通过使用@RequestParam,你已经间接地要求Spring在调用你的控制器之前提前解析你的参数。您应该能够做的(如果文档正确)是独立于控制器内部请求参数:

配置(application.properties):

spring.servlet.multipart.enabled = true
spring.servlet.multipart.resolve-lazily = true

控制器:

@PostMapping(path = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<Void> postUpload(HttpServletRequest rawRequest) {

    multipartResolver.setResolveLazily(true); // unclear why this is exists
    MultipartHttpServletRequest request = multipartResolver.resolveMultipart(rawRequest);

    String p1 = request.getParameter("first-parameter");
    String p2 = request.getParameter("second-parameter");
    System.out.println("first-parameter="+p1+", second-parameter"+p2);

    multipartResolver.cleanupMultipart(request);
    return new ResponseEntity<Void>(HttpStatus.ACCEPTED);
}

我发现,resolve lazy的一个有用方面是,它允许您为某些rest控制器编写自己的解析器,同时为其他控制器使用内置解析器(请参阅此处的答案)。换句话说,您不必使用<code>spring.servlet.multipart。enabled=false以使解析器工作。与我之前看到的其他建议相比,这是一个小小的突破。

 类似资料:
  • 当我尝试用我的代码下载文件时,我出现了这样的错误: HTTP状态500-请求处理失败;嵌套异常是org.springframework.web.multipart.multipartException:无法解析多部分servlet请求;嵌套异常是java.io.ioException:临时上载位置[/tmp/tomcat.5139949927832460132.8080/work/tomcat/l

  • 我们正在将csv文件从Angular上传到Spring boot 2。x app包含约100万条记录,这100万条记录在间隔超过20分钟后在服务器上处理。csv文件请求将文件从Angular加载到Spring boot需要更多时间,在Spring boot应用程序中接收文件大约需要20分钟。 在application.yml文件中配置 servlet:多部分:已启用:真实最大文件大小:200MB最

  • 安装Windows服务时,有两个选项可以在Windows启动时自动启动Windows服务。一个是自动,另一个是自动(延迟启动)。详细来说,这两者有什么区别? 例如,如果您使用wixtoolset创建安装程序,ServiceConfig元素具有DelayedAutoStart属性。当服务在启动时启动时,这会对发生的事情产生什么影响? WiX留档:ServiceConfig元素

  • 当用户滚动内容时,我试图添加一个浮动div,它几乎可以工作,但在动画上几乎没有延迟,我需要当scrollTop到达浮动div时,浮动div应该与滚动一起动画 小提琴连杆

  • 我正在使用Spring Boot(1.5.7)和ng2文件上传(1.2.1)将文件上传到服务器。 所以我遇到了下一个问题,当文件上传开始并中断时(例如关闭浏览器选项卡),Spring Boot会记录下一个错误(两次): 当我将@ExceptionHandler添加到@ControllerAdvice时: 和应用程序的下一个属性。属性: 现在,当文件上载中断时,@ExceptionHandler会按

  • 以及multipartConfigElement 但是当我向REST服务发送多部分消息时,仍然会出现以下异常: servlet[dispatcherServlet]在路径[/dev]的上下文中的servlet.service()引发异常[请求处理失败;嵌套异常是java.lang.IllegalArgumentException:预期的multiparthttpServletRequest:是否配