GCS预签名URL v4上传m4a文件损坏,mp3正常求助
问题:GCS上传m4a文件损坏,mp3可正常播放
目标
向Google Cloud Storage(GCS)上传大于40MB的m4a音频文件
当前实现方式
- 后端生成GCS PUT方法的v4预签名URL
- 前端通过Axios使用该URL上传文件
问题现象
- mp3文件上传后可在GCS界面正常播放,下载到本地也能正常播放
- m4a文件上传后损坏,GCS界面无法播放,下载到Mac/PC后同样无法播放
- 不同大小的mp3、m4a文件均出现此一致问题
相关代码
Python后端生成预签名URL
bucket = client.bucket(bucket_name) blob = bucket.blob(filename) signed_url = blob.generate_signed_url( version="v4", expiration=timedelta(minutes=60), method="PUT", )
React前端上传代码(存在问题)
async function upload(file: File, signed_url: str) { const formData = new FormData() formData.append('file', file) await axios.put(signed_url, formData, { headers: { 'Content-Type': file.type }, }) }
问题原因
GCS的PUT预签名URL要求请求体必须是原始文件内容,但当前前端用FormData包装了文件,导致上传到GCS的内容包含FormData的HTTP边界、字段描述等额外信息,直接破坏了m4a的容器结构。mp3作为流式音频格式对异常内容容错性较高,所以未表现出明显损坏,但这也是不符合规范的上传方式。
解决方案
直接上传文件本身,不要使用FormData包装,修改前端代码如下:
async function upload(file: File, signed_url: string) { await axios.put(signed_url, file, { headers: { 'Content-Type': file.type }, }) }
补充说明
如果上传的m4a文件远大于40MB(例如超过100MB),建议启用GCS的分块上传机制,避免因网络波动导致上传失败。分块上传需要后端生成对应分块的预签名URL,前端分块上传完成后再触发合并操作,但当前问题的核心是FormData的错误使用,修正后即可解决文件损坏问题。
内容的提问来源于stack exchange,提问作者not_fubar_yet
相关产品推荐
相关产品推荐

