You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

iOS环境下Fetch请求提交音频文件时数据丢失问题求助

iOS上Fetch发送FormData音频Blob丢失内容的解决方案

我之前也碰到过iOS Safari里Fetch提交FormData时Blob内容丢失的问题,大概率是你手动设置的那些HTTP头和FormData的自动处理冲突了,iOS的WebKit在这方面的兼容性比较严格。咱们一步步来改:

核心问题分析

当你用FormData作为fetch的body时,浏览器会自动生成正确的multipart/form-data相关头(包括Content-Length、分隔符等),而你手动设置的Content-LengthContent-Range这些头会干扰iOS WebKit的解析逻辑,导致Blob内容没有被正确序列化到请求体里。

具体修改步骤

1. 移除冲突的HTTP头

把这些手动设置的头全部删掉:

  • Content-Length
  • Content-Range
  • Content-Transfer-Encoding
  • Accept-Ranges

这些头应该由浏览器自动处理,手动设置反而会破坏FormData的正确格式。

2. 确保Blob的有效性(iOS专属优化)

有时候iOS对某些来源的Blob处理有问题,可以尝试把原始Blob转成ArrayBuffer再重新构造一次Blob,确保数据完整性:

// 先把data转成ArrayBuffer再转Blob
const arrayBuffer = await data.arrayBuffer();
const fixedBlob = new Blob([arrayBuffer], { type: 'audio/wav' });

3. 修改后的完整代码

sendDataToServer = async (data, timecode, location = "postFileWebm/") => { 
  // data is a blob 
  // timecode is current time in millisecons 
  // location is the function to run in the flask server 

  // iOS兼容性处理:转成ArrayBuffer再重构Blob
  const arrayBuffer = await data.arrayBuffer();
  const fixedBlob = new Blob([arrayBuffer], { type: 'audio/wav' });

  const formData = new FormData(); 
  // 给文件名加上后缀,方便后端识别格式
  formData.append("file", fixedBlob, `${this.props.id}${timecode}.wav`); 

  // 调试:确认Blob大小,排查数据是否有效
  console.log("Blob size:", fixedBlob.size);
  console.log("FormData file:", formData.get("file"));

  return fetch(`${SERVER_URL}/${location}`, { 
    headers: { 
      name: `${this.props.id}${timecode}`, 
      segment: count, 
      id: this.props.id, 
      label: this.state.label, 
      gameId: this.props.gameId, 
      extension: "wav", 
      // 移除所有和文件传输相关的自动头
    }, 
    method: "POST", 
    body: formData, 
  }); 
}; 

额外调试建议

  • 用Safari的开发者工具(连接iOS设备后)查看请求的Request Payload,确认Blob内容是否已经正确包含在请求体里。
  • 后端可以打印接收的请求头和内容长度,对比iOS和其他设备的差异,进一步定位问题。

这种修改应该能解决iOS上Blob内容丢失的问题,我之前处理类似的音频上传问题时,就是靠移除手动设置的文件头和重构Blob解决的。

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

火山引擎 最新活动