基于Fetch API的FormData CSV文件上传报错求助
问题分析与修复方案
核心错误点
1. FormData序列化导致签名无效
FormData是特殊的表单数据对象,无法通过JSON.stringify()直接序列化,这样得到的结果是{},会直接导致后端签名验证失败,这是上传报错的核心原因。
2. 调用代码逻辑错误
fetchFormData函数内部已经完成了response.json()的解析,返回的是JSON数据而非Response对象。调用时再执行response.json()会报错,且!response.ok的判断完全无效——因为此时的response是数据,不具备ok属性。
3. 潜在请求头问题
上传FormData时,浏览器会自动生成包含boundary的Content-Type头,手动添加该头反而会破坏上传格式,代码中虽未手动设置,但需注意不要额外添加。
修正后的代码
封装的fetchFormData函数
const fetchFormData = async (url, method = 'POST', formData) => { const secret = process.env.NEXT_PUBLIC_SECRET_KEY || ''; const token = Cookies.get('accessToken'); if (!secret) { throw new Error('Secret key is not defined'); } if (!token) { throw new Error('Token is not defined'); } // 不能直接序列化FormData,需根据后端要求构造签名参数 // 示例:提取文件关键信息,或使用后端约定的固定参数 const signPayload = { fileName: formData.get('file')?.name || '', fileSize: formData.get('file')?.size || 0 }; const nonce = generateNonce(); const timestamp = generateTimestamp(); const signature = generateSignature(JSON.stringify(signPayload), secret, nonce, timestamp); const headers = { 'Nonce': nonce, 'Timestamp': timestamp, 'Signature': signature, 'Authorization': `Bearer ${token}`, // 禁止手动设置Content-Type,浏览器会自动处理multipart/form-data及boundary }; try { const response = await fetch(url, { method, headers, body: formData, }); if (!response.ok) { // 优先解析后端返回的错误信息 const errorData = await response.json().catch(() => null); throw new Error(errorData?.message || `HTTP error! Status: ${response.status}`); } return await response.json(); } catch (error) { console.error('Error uploading file:', error); throw error; } }; export default fetchFormData;
修正后的调用代码
const formData = new FormData() formData.append('file', bulkFile) const apiUrl = `${process.env.NEXT_PUBLIC_API_URL_LIVE}/uploadProducts` try { // 直接接收解析后的JSON数据 const responseData = await fetchFormData(apiUrl, 'POST', formData) console.log('上传成功:', responseData) } catch(error) { console.log(error.message) }
关键说明
- 签名生成逻辑需和后端协商确认,必须使用后端认可的参数生成签名,不能直接序列化FormData。
- 确保
generateNonce、generateTimestamp、generateSignature的算法与后端完全一致,否则会持续出现签名验证失败的问题。
内容的提问来源于stack exchange,提问作者Luix
相关产品推荐
相关产品推荐

