You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring接收multipart/related请求无法获取无Content-Disposition的部分如何解决

问题原因

Spring默认的StandardServletMultipartResolver是为multipart/form-data场景设计的,只会把携带Content-Disposition: form-data头的请求部分识别为合法的Multipart对象,不带该头的multipart/related部分会被直接过滤,所以无法通过MultipartHttpServletRequest获取。

解决方案1:使用Apache Commons FileUpload手动解析请求

该方案灵活性最高,不需要修改全局Multipart配置之外的公共逻辑,适配第三方不可修改的请求格式。

步骤1:引入依赖

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.5</version>
</dependency>

步骤2:关闭Spring默认Multipart解析

在application.yml中添加配置:

spring:
  servlet:
    multipart:
      enabled: false

步骤3:控制器中编写解析逻辑

@RestController
@RequestMapping("/stowrs")
public class StowController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @PostMapping(value = "/studies", consumes = MediaType.MULTIPART_RELATED_VALUE)
    public void store(HttpServletRequest request) throws Exception {
        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        if (!isMultipart) {
            return;
        }
        ServletFileUpload upload = new ServletFileUpload();
        // 解析所有请求部分,不会过滤无Content-Disposition的part
        FileItemIterator iter = upload.getItemIterator(request);
        while (iter.hasNext()) {
            FileItemStream item = iter.next();
            String contentType = item.getContentType();
            try (InputStream inputStream = item.openStream()) {
                String content = new String(inputStream, StandardCharsets.UTF_8);
                logger.info("Part Content-Type: {}, Content: {}", contentType, content);
                // 按业务需求处理对应part即可
            }
        }
    }
}

如果项目中还存在其他使用multipart/form-data的接口,更推荐该方案,不需要修改现有接口逻辑即可兼容两种multipart格式。

步骤1:实现自定义解析器

public class MultipartRelatedResolver extends StandardServletMultipartResolver {
    @Override
    public boolean isMultipart(HttpServletRequest request) {
        String contentType = request.getContentType();
        // 同时支持form-data和related两种multipart格式
        return super.isMultipart(request) || (contentType != null && contentType.startsWith(MediaType.MULTIPART_RELATED_VALUE));
    }

    @Override
    public MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException {
        MultipartHttpServletRequest multipartRequest = super.resolveMultipart(request);
        try {
            Collection<Part> parts = request.getParts();
            for (Part part : parts) {
                String contentDisposition = part.getHeader(HttpHeaders.CONTENT_DISPOSITION);
                // 把无form-data标识的part手动加入Multipart请求对象
                if (contentDisposition == null || !contentDisposition.startsWith("form-data")) {
                    // 可自定义命名规则,比如用索引、contentType作为key
                    String partKey = "part_" + part.getContentType() + "_" + part.hashCode();
                    ((StandardMultipartHttpServletRequest) multipartRequest).getMultipartFiles().put(partKey, new StandardMultipartFile(part, partKey));
                }
            }
        } catch (Exception e) {
            throw new MultipartException("解析multipart/related请求失败", e);
        }
        return multipartRequest;
    }
}

步骤2:注册自定义解析器为Bean

@Configuration
public class MultipartConfig {
    @Bean
    public MultipartResolver multipartResolver() {
        return new MultipartRelatedResolver();
    }
}

配置完成后依然可以使用MultipartHttpServletRequest作为控制器参数获取所有请求部分。

内容的提问来源于stack exchange,提问作者Shin DongJin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.21 06:24:04