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










