react-bootstrap表单文件上传失败 返回400请求体解析错误
问题排查与修复方案
定位到的核心错误
1. 手动设置multipart/form-data请求头导致请求体解析失败
这是返回There was an error parsing the body、报400错误的直接原因。
使用FormData作为请求体时,浏览器会自动生成带随机boundary分隔符的Content-Type请求头,格式为Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryxxx,后端依赖这个boundary值拆分不同的表单字段。手动写死"Content-Type": "multipart/form-data"会覆盖浏览器自动生成的合法头,缺失必须的boundary参数,后端自然无法解析请求体。Postman调用时会自动补全正确的boundary参数,所以可以正常返回结果。
2. Switch开关组件取值逻辑错误
type="switch"的Form.Check本质是复选框组件,开关的布尔状态存储在e.target.checked属性中,代码中取的e.target.value默认是固定字符串"on",和开关是否开启完全无关,会导致传给后端的ipfs、image_kit字段值不符合接口预期。
3. 逻辑瑕疵(不直接导致报错,但建议修复)
原有Promise链存在断层:第一个处理返回结果的then没有返回值,第二个then拿到的参数永远是undefined;缺少上传前的文件非空校验、HTTP状态码校验,容易发起无效请求。
修复步骤
- 删除fetch请求headers中手动配置的
"Content-Type": "multipart/form-data",让浏览器自动生成合法请求头 - 修改两个开关的onChange回调,取值从
e.target.value改为e.target.checked,获取正确的布尔状态 - 补充基础参数校验、HTTP状态校验,修正Promise链逻辑
修复后代码
状态同步逻辑
const changeHandler = (event) => { setSelectedFile(event.target.files[0]); }; const ifpsChange = (e) => { // 从checked属性取开关布尔状态 setIpfsBool(e.target.checked); }; const imgKitChange = (e) => { setImgBool(e.target.checked); };
上传请求逻辑
const uploadMetaData = (e) => { // 上传前非空校验 if (!selectedFile) { alert("请先选择要上传的Excel文件"); return; } setIsLoading(true); const sc = process.env.REACT_APP_FAST_KEY; let formData = new FormData(); formData.append("file", selectedFile); formData.append("ipfs", ipfsBool); formData.append("image_kit", imgBool); formData.append("city", pannel); fetch("https://pythonapi.metropolisworld.io/addCitydata", { method: "POST", headers: { // 移除手动设置的Content-Type,仅保留自定义请求头 secretkey: sc, }, body: formData, }) .then((response) => { // 增加HTTP状态码校验 if (!response.ok) { throw new Error(`请求失败,状态码:${response.status}`); } return response.json(); }) .then((result) => { console.log("Success:", result['detail']); setIsLoading(false); // 可在此处添加上传成功提示、页面跳转等业务逻辑 }) .catch((error) => { console.error("Error:", error); setIsLoading(false); // 可在此处添加上传失败提示逻辑 }); };
内容的提问来源于stack exchange,提问作者Joby Ingram-Dodd
相关产品推荐
相关产品推荐

