React发送含JSON与文件的FormData报错,如何排查解决?
问题现象
前端使用React通过FormData发送包含图片和JSON数据的POST请求到Spring Boot后端,Postman测试接口正常,但浏览器请求时报错:"message": "Required request part 'swimArea' is not present",即使移除文件相关代码,错误依然存在。
核心问题与修复方案
1. 重复JSON序列化导致数据格式错误
你的前端代码中,swimArea已经是手动拼接的JSON字符串,却又调用了JSON.stringify()二次序列化,导致最终传递给后端的是转义后的嵌套字符串(例如"{\"swimArea\": {...}}"),后端无法将其解析为AddBathingPlaceRequest对象,因此识别不到swimArea参数。
修复:
去掉多余的JSON.stringify(),或者更规范地先定义JS对象再序列化:
// 方式1:直接使用已有的JSON字符串,无需二次序列化 const swimArea = "{\"swimArea\" : {\"name\": \"aTESTTEST\", \"longitude\": \"15.47\", \"latitude\": \"56.25\"}}"; formData.append('swimArea', swimArea); // 方式2(推荐):先定义JS对象,再统一序列化,避免手动拼接JSON出错 const swimAreaObj = { swimArea: { name: "aTESTTEST", longitude: "15.47", latitude: "56.25" } }; formData.append('swimArea', JSON.stringify(swimAreaObj));
2. 手动设置请求头导致解析失败
当使用FormData作为fetch请求的body时,浏览器会自动生成正确的multipart/form-data请求头,包括自动生成的boundary分隔符。你手动设置的Content-Type会覆盖自动生成的头,导致boundary不匹配,后端无法正确解析表单数据。
另外,Access-Control-Allow-*系列头是后端响应头,前端请求中添加这些头没有任何作用,反而可能干扰请求。
修复:
移除手动设置的Content-Type和CORS相关请求头:
const requestOptions = { method: "POST", // 仅保留必要的请求头(如Authorization,无则可省略headers) headers: { // "Authorization": "Bearer xxx" // 如果需要身份验证的话 }, body: formData, };
3. 文件获取方式错误
e.target.file的写法不正确,input[type="file"]的文件需要通过files属性获取,正确写法为e.target.elements.file.files[0](假设你的文件输入框name或id为file)。
修复:
formData.append("file", e.target.elements.file.files[0]);
修改后的完整前端代码
const submitForm = (e: any) => { e.preventDefault(); // 推荐使用JS对象序列化的方式 const swimAreaObj = { swimArea: { name: "aTESTTEST", longitude: "15.47", latitude: "56.25" } }; const formData = new FormData(); formData.append('swimArea', JSON.stringify(swimAreaObj)); // 正确获取文件 formData.append("file", e.target.elements.file.files[0]); const requestOptions = { method: "POST", // 移除多余的请求头,由浏览器自动生成multipart/form-data头 body: formData, }; fetch( "http://localhost:8080/api/v1/bathplace/newBathingPlace", requestOptions ) .then((response) => response.json()) .then((data) => { // 处理返回数据 }) .catch(err => console.error("请求错误:", err)); };
验证步骤
- 打开浏览器开发者工具(F12),切换到Network标签;
- 触发请求,查看对应的POST请求;
- 检查Headers中的
Content-Type是否为multipart/form-data; boundary=----WebKitFormBoundaryxxxx(由浏览器自动生成); - 查看Form Data部分,确认
swimArea的值是正确的JSON字符串,而非转义后的嵌套字符串。
内容的提问来源于stack exchange,提问作者Tronjesson

