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

AngularJS向Spring Boot发送带图片对象时提示非multipart请求异常

问题根因

报错由两处代码错误直接导致:

  • 后端参数注解使用逻辑错误:multipart/form-data请求不支持同时使用@RequestBody和@RequestParam接收参数。@RequestBody会消费整个请求输入流做JSON反序列化,会直接破坏multipart请求的分片解析流程,导致Spring无法识别这是一个multipart请求。
  • 前端请求构造错误:你仅将文件放入了FormData实例,最终发请求时传递的是普通JS对象{file, personRequest},Angular HttpClient会默认将这类普通对象编码为application/json格式,请求根本不是multipart类型,自然抛出对应异常。另外手动设置Content-Type: multipart/form-data头的操作本身也是错误的,会丢失浏览器自动生成的boundary分隔符,同样会导致解析失败。
修复步骤

1. 调整后端Controller代码

将@RequestBody替换为专门处理multipart分片的@RequestPart注解,该注解支持自动将multipart中JSON格式的分片反序列化为Java对象,修改后代码如下:

@PostMapping("multi")
public String multi(@RequestParam MultipartFile file, @RequestPart PersonRequest personRequest) throws IOException {
    Binary fileBinary = new Binary(file.getBytes());
    log.info("接收文件: {}, 接收业务参数: {}", file.getOriginalFilename(), personRequest);
    // 直接将fileBinary设置到关联实体对象中,完成入库等后续逻辑
    return "success";
}

如果上述写法在你的Spring版本中存在兼容性问题,可以用更稳妥的兼容方案:接收JSON字符串参数后手动反序列化:

@PostMapping("multi")
public String multi(@RequestParam MultipartFile file, @RequestParam String personRequest) throws IOException {
    Binary fileBinary = new Binary(file.getBytes());
    // 用Spring Boot内置的Jackson将JSON字符串转为PersonRequest对象
    PersonRequest req = new ObjectMapper().readValue(personRequest, PersonRequest.class);
    log.info("接收文件: {}, 接收业务参数: {}", file.getOriginalFilename(), req);
    return "success";
}

2. 调整前端Angular请求代码

核心要求:所有参数必须追加到同一个FormData实例中,直接传递FormData实例作为请求体,不要手动设置Content-Type请求头。
如果后端用@RequestPart的写法,前端需要将业务对象包装为JSON类型的Blob再追加到FormData,保证后端可以正确识别分片的内容类型:

addPersonWithIMG(image:File, personRequest: PersonRequest):Observable<any>{
    const formData = new FormData();
    // 追加文件参数,参数名和后端@RequestParam声明的参数名保持一致
    formData.append('file', image);
    // 将业务对象转为JSON Blob,指定内容类型为application/json
    const reqBlob = new Blob([JSON.stringify(personRequest)], { type: 'application/json' });
    formData.append('personRequest', reqBlob);
    // 直接传递formData作为请求体,不要设置任何自定义Content-Type头
    return this.http.post(`${this.baseUrl}/multi`, formData);
}

如果后端用兼容的字符串参数接收方案,直接追加JSON字符串即可:

addPersonWithIMG(image:File, personRequest: PersonRequest):Observable<any>{
    const formData = new FormData();
    formData.append('file', image);
    formData.append('personRequest', JSON.stringify(personRequest));
    return this.http.post(`${this.baseUrl}/multi`, formData);
}
验证要点

改完后可以在浏览器开发者工具的网络面板查看请求头,正常的请求头会自动带Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryxxxx格式的内容,不存在boundary缺失、Content-Type为application/json的情况,后端可以同时拿到文件和业务参数,不会再抛出原异常。
另外注意:你DTO里注释掉的private Binary image字段不需要保留,文件已经通过MultipartFile单独接收,拿到字节数组后直接转Binary存入实体即可,不需要前端传递Binary类型字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 03:27:21