Spring POST multipart/form-data, 请求部分始终为空

Spring POST multipart/form-data, request parts always empty

我有一个简单的 REST 控制器,用于接受从 HTML 表单上传的文件。项目是SpringBoot 2.6.1和Java17。但是问题也在SpringBoot 2.3.7和Java15.

@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);
    }

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

请考虑使用 ContentCachingRequestWrapper。

它是 spring 的内置功能,可帮助您读取缓存从输入流和 reader 中读取的所有内容。

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

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