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

Spring Boot无法解析Multipart请求:Content-Type不支持问题排查

问题排查:前端Multipart表单请求Spring Boot接口报错Content-Type不支持

问题现象

前端提交带附件的表单时,调用后端Spring Boot接口触发如下错误:

Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content-Type 'multipart/form-data;boundary=----WebKitFormBoundaryn1nNr7iOEen0Aykw' is not supported]

Postman测试后端接口功能正常,前端请求第三方测试接口也能得到正常响应,怀疑后端Controller写法存在问题,请求协助排查。

相关代码

前端JS代码

async function submitDataToBackend(data, file, formDataa) {
  const formatedFormData = dataFormattingIntoJSON(data);
  const formData = new FormData();
  formData.append('form', formatedFormData);
  if (file) {
    formData.append('CV', file);
  }

  for (const pair of formData.entries()) {
    console.log('key: ', pair[0], ';       value: ', pair[1]);
  }

  const headers = new Headers();
  headers.append("Content-Type", "multipart/form-data");

  fetch('http://localhost:8081/api/v1/forms/newproject', {
    method: 'POST',
    headers: headers,
    body: formData,
  })
      .then((response) => response.json())
      .then((data) => {
        console.log('response from server: ', data);
      })
      .catch((error) => {
        console.log(error);
      });
}

后端Controller代码

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/forms")
@Tag(name = "Forms Controller", description = "Forms API")
@Slf4j
public class FormsController {
    private final EmailServiceMarsNet emailServiceMarsNet;

    @PostMapping(value="/newproject",consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
    @Operation(summary = "Method for send email form 'Start your NEW project'")
    public StartProjectDTO sendStartProjectRequest(@RequestPart(value = "form") @Valid StartProjectDTO request,
                                                   @RequestPart(value = "CV", required = false) MultipartFile file){
        log.info(request.toString());
        emailServiceMarsNet.sendFormStartYourProjectNew(request,file);
        return request;
    }
}

问题分析与解决方案

核心问题1:前端手动设置Content-Type导致boundary失效

当使用FormData作为fetch请求的body时,浏览器会自动生成包含正确boundary的Content-Type头。前端手动设置Content-Type: multipart/form-data会覆盖浏览器自动生成的头,丢失boundary信息,导致后端无法正确解析multipart格式的请求体,从而触发HttpMediaTypeNotSupportedException。

核心问题2:form字段的JSON数据格式可能无法被后端解析

如果dataFormattingIntoJSON(data)返回的是JSON对象而非字符串,直接通过formData.append('form', formatedFormData)添加的话,浏览器会将其转换为[object Object]字符串,后端无法将该字符串反序列化为StartProjectDTO对象。

修复后的前端代码

async function submitDataToBackend(data, file, formDataa) {
  const formatedFormData = dataFormattingIntoJSON(data);
  const formData = new FormData();
  
  // 确保form字段是带正确媒体类型的JSON内容
  const formBlob = new Blob([JSON.stringify(formatedFormData)], { type: 'application/json' });
  formData.append('form', formBlob);
  
  if (file) {
    formData.append('CV', file);
  }

  for (const pair of formData.entries()) {
    console.log('key: ', pair[0], ';       value: ', pair[1]);
  }

  // 移除手动设置的Content-Type,由浏览器自动生成
  fetch('http://localhost:8081/api/v1/forms/newproject', {
    method: 'POST',
    body: formData,
  })
      .then((response) => response.json())
      .then((data) => {
        console.log('response from server: ', data);
      })
      .catch((error) => {
        console.log(error);
      });
}

后端代码确认

后端Controller的写法是正确的:

  • @PostMapping指定了consumes = MediaType.MULTIPART_FORM_DATA_VALUE,明确接收multipart类型请求
  • @RequestPart用于接收multipart请求中的不同部分,form对应JSON格式的DTO,CV对应可选的文件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 07:53:09