当前位置: 首页 > 新闻动态 > 网络资讯

Spring Boot 中如何在单个请求中同时上传文件与 JSON 数据

作者:花韻仙語 浏览: 发布日期:2026-01-01
[导读]:在SpringBootREST接口中,无法直接用@RequestBody+@RequestPart混合接收JSON和文件,因其底层解析冲突;正确做法是将MultipartFile作为DTO的字段,并使用@RequestPart统一接收整个表单数据。

在 spring boot rest 接口中,无法直接用 `@requestbody` + `@requestpart` 混合接收 json 和文件,因其底层解析冲突;正确做法是将 `multipartfile` 作为 dto 的字段,并使用 `@requestpart` 统一接收整个表单数据。

在 Spring Boot 中,HTTP 请求体(Content-Type: multipart/form-data)本质是一个二进制边界分隔的表单数据结构,不支持同时解析为纯 JSON(application/json)和多部分(multipart/form-data)两种格式。因此,当你在 @PostMapping 中声明 consumes = {APPLICATION_JSON_VALUE, MULTIPART_FORM_DATA_VALUE},Spring 会因媒体类型冲突或消息转换器(HttpMessageConverter)不匹配而返回 415 Unsupported Media Type 错误——这是根本性设计限制,而非配置疏漏。

✅ 正确方案:统一使用 multipart/form-data,并将 JSON 字段与文件共同封装在 @RequestPart 中

  1. 修改 DTO,嵌入 MultipartFile 字段(不推荐)⚠️
    虽然答案中建议“在 PortfolioFileSaveRequestDto 中添加 MultipartFile 字段”,但需注意:Java Bean 不应直接持有 MultipartFile,因其不是可序列化的标准数据类型,且违反 DTO 职责分离原则(DTO 应仅承载传输数据,而非 Servlet 特定对象)。该做法易导致测试困难、Jackson 序列化异常及潜在内存泄漏。

  2. 推荐实践:保持 DTO 纯净,用 @RequestPart 分别绑定各表单项
    将 JSON 数据以字符串形式提交,再手动反序列化;或更简洁地——让前端将 JSON 字段作为独立表单项发送(如 data),后端用 @RequestPart("data") String jsonData 接收并转为对象:

@PostMapping(value = "/file/new", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity> createFile(
        HttpServletRequest servletRequest,
        @RequestPart("data") @Valid String jsonData,           // JSON 字符串(表单项名:data)
        @RequestPart("file") MultipartFile file) {             // 文件(表单项名:file)

    // 手动反序列化 JSON
    PortfolioFileSaveRequestDto request = new ObjectMapper()
            .readValue(jsonData, PortfolioFileSaveRequestDto.class);

    List tokenInfo = jwtProvider.authorizeJwt(servletRequest.getHeader(AUTHORIZATION));
    Portfolio portfolio = portfolioService.saveFile(request, user.getUsername(), profile, file);

    return ResponseEntity.status(HttpStatus.CREATED)
            .body(DefaultResponseDto.success(portfolio));
}

? 前端请求示例(JavaScript Fetch):

const formData = new FormData();
formData.append("data", JSON.stringify({
    fileName: "report.pdf",
    description: "Q3 financial summary"
}));
formData.append("file", fileInput.files[0]);

fetch("/api/file/new", {
    method: "POST",
    body: formData
    // ⚠️ 不要设置 Content-Type!浏览器会自动设置 boundary
});

✅ 补充说明:

  • @RequestPart 是处理 multipart/form-data 的标准注解,支持按名称绑定任意表单项(字符串、文件、甚至嵌套 JSON 字符串);
  • 避免 @RequestBody 与 multipart 混用,Spring 不支持同一请求体被多个消息转换器争抢解析;
  • 若需强类型校验,可在 Controller 层反序列化后立即调用 Validator.validate(),或封装为自定义 @ValidJson 注解实现自动校验。

总结:没有“JSON + 文件”的原生混合绑定,只有“统一 multipart + 分项提取 + 按需解析”这一可靠路径。 保持接口语义清晰、DTO 职责纯粹,才是 Spring Boot 多部分上传的最佳实践。

免责声明:转载请注明出处:http://shjed.com/news/277690.html

扫一扫高效沟通

多一份参考总有益处

免费领取网站策划SEO优化策划方案

请填写下方表单,我们会尽快与您联系
感谢您的咨询,我们会尽快给您回复!