【问题标题】:Spring POST multipart/form-data, request parts always emptySpring POST multipart/form-data,请求部分始终为空
【发布时间】:2021-12-03 12:58:15
【问题描述】:

我有一个简单的 REST 控制器,用于接受从 HTML 表单上传的文件。该项目是 Spring Boot 2.6.1 和 Java 17。但问题也出现在 Spring Boot 2.3.7 和 Java 15 中。

@PostMapping(path = "/file", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public void handleFileUpload(@RequestParam("file") MultipartFile file) {
    fileService.upload(file.getInputStream(), file.getOriginalFilename());
}

问题是file 始终为NULL。我发现了很多关于设置MultipartResolver bean 或启用spring.http.multipart.enabled = true 的不同答案,但没有任何帮助。我有一个日志过滤器作为链中的第一个过滤器。在过滤器链中调试后,我发现调用request.getParts() 可以使一切正常。我的过滤器如下所示:

public class LoggingFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        BufferedRequestWrapper bufferedRequest = new BufferedRequestWrapper(httpServletRequest);
        BufferedResponseWrapper bufferedResponse = new BufferedResponseWrapper((HttpServletResponse) response);

        filterChain.doFilter(bufferedRequest, bufferedResponse);

        logRequest(httpServletRequest, bufferedRequest);
        logResponse(httpServletRequest, bufferedResponse);
    }

我将过滤器更改为:

public class LoggingFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;

        if (request.getContentType() != null && request.getContentType().startsWith("multipart/form-data")) {
            httpServletRequest.getParts(); // Trigger initialization of multi-part.
        }

        BufferedRequestWrapper bufferedRequest = new BufferedRequestWrapper(httpServletRequest);
        BufferedResponseWrapper bufferedResponse = new BufferedResponseWrapper((HttpServletResponse) response);

        filterChain.doFilter(bufferedRequest, bufferedResponse);

        logRequest(httpServletRequest, bufferedRequest);
        logResponse(httpServletRequest, bufferedResponse);
    }

一切正常。我的问题是;为什么需要这个?有没有更好的方法来做到这一点?

【问题讨论】:

  • 您需要将bufferedRequestbufferedResponse 向下传递而不是常见请求。
  • 我实际上已经这样做了。我正在清理代码a但是,并且犯了一个错误。我已经更新了代码以反映我的实际代码。
  • 在您的控制器中使用 @RequestPart 而不是 @RequestParam
  • 我试过@RequestPart@RequestParam 并使用@ModelAttribute 包裹MultipartFile。我还在 REST 控制器中注入了 HttpRequest 并调用 request.getParts() 正在重新调整一个空数组。这些部件在某处被消耗,因为它们在某个时候可用,但在到达 REST 控制器时丢失。
  • BufferedRequestWrapper 在哪里?它是内置在 Spring 中的还是什么?过去,我使用 ContentCachingRequestWrapper 而不是 BufferedRequestWrapper。请注意,对于多部分文件,spring 已经有一个包装器... MultipartHttpServletRequest

标签: java spring spring-boot multipartform-data


【解决方案1】:

请考虑使用 ContentCachingRequestWrapper。

它是spring内置的,可以帮助你读取缓存从输入流和阅读器读取的所有内容。

请注意,对于多部分文件,spring 已经有一个包装器... MultipartHttpServletRequest

请参考: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/util/ContentCachingRequestWrapper.html

【讨论】:

    猜你喜欢
    • 2016-01-29
    • 2023-04-01
    • 1970-01-01
    • 2017-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-05
    相关资源
    最近更新 更多