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

基于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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 12:57:03