Django-React下Google Cloud Storage签名URL上传失败问题
GCS签名URL跨栈上传失败排查修复
核心问题汇总
- 前端请求方法与签名约定不匹配:GCS单文件PUT类型签名URL要求使用
PUT方法发起请求,现有React代码错误使用POST方法 - 前端携带非法请求头:
Access-Control-Allow-Origin、Access-Control-Allow-Methods是服务端CORS响应的专属头,前端请求时携带这类未纳入签名计算范围的头,会直接触发签名校验失败 - 上传数据格式错误:PUT方式上传不需要将文件包装为
FormData对象,FormData会自动添加分隔符、内容描述等额外字节,与签名时约定的请求体内容不一致 - 签名URL转义错误:贴出的curl命令、CreateAssets接口地址中,参数分隔符
&被错误转义为HTML实体&,会导致参数解析异常 - CORS配置桶不匹配:执行CORS配置命令时指定的桶是
production-my-storage,实际上传使用的桶是production-videoo-storage,CORS规则未生效到目标桶 - 签名本身校验失败:排除前端问题后裸curl测试仍返回签名不匹配,说明后端签名生成逻辑存在问题
分步修复方案
1. 先修复后端签名生成逻辑
从curl返回的StringToSign内容看,签名的基础结构(PUT方法、无额外Content-MD5、无自定义头、过期时间、对象路径)是符合规范的,优先排查以下问题:
- 确认签名使用的服务账号私钥与
GoogleAccessId参数对应的账号videoo-348016@appspot.gserviceaccount.com完全匹配,私钥内容无转义、缺漏 - 生成签名URL后禁止做HTML实体转义,返回给前端的URL必须是原始格式,参数用原生
&分隔,不能出现& - 签名时指定的HTTP方法、Content-Type必须和前端实际请求完全一致:如果签名时未指定Content-Type,前端请求时要么不携带Content-Type头,要么传入的值和签名时填写的值完全一致,不能随意填写
video/mp4
2. 修正React端代码
删除多余逻辑,修正后的上传代码参考:
export const UploadVideo = async (file, signedurl, asset_uuid) => { let resultState = { state: '', data: {} }; let config = { method: 'PUT', // 必须和签名约定的方法一致 url: signedurl, headers: { // 仅保留签名时约定的Content-Type,未约定则删除该头 'Content-Type': file.type }, data: file, // 直接传入原始File对象,不要包装FormData }; try { const response = await axios(config); console.log(JSON.stringify(response.data)); resultState.state = 'success'; } catch (error) { resultState.state = 'error'; resultState.data.message = error.message; window.toastr.error(error.message); console.log(error) } return resultState; } export const CreateAssets = async (data, key) => { let resultState = { state: '', data: {} }; // 把URL里的&全部替换为&,修正参数转义错误 await axios.get(`https://origin/asset/create/?category=1&title="${data[key].title}"&size=1`) .then(res => { resultState.state = 'success'; resultState.data = res.data; }).catch((err) => { resultState.state = 'error'; resultState.data['message'] = err.message; }) return resultState; }
3. 重新配置目标桶CORS规则
现有CORS规则的内容已经满足上传需求,只需要给正确的目标桶重新执行配置命令即可:
gsutil cors set google-storage-cors.json gs://production-videoo-storage
4. 验证流程
- 先从后端拿到未转义的原始签名URL,用curl测试,注意URL里的参数分隔符必须是
&,不能带&:curl -X PUT --upload-file /Users/utku/Desktop/cat.mp4 "替换为你的原始签名URL" - curl返回200状态码、无错误信息,说明签名逻辑正常
- 再调用前端上传逻辑,即可正常完成上传
内容的提问来源于stack exchange,提问作者london_utku
相关产品推荐
相关产品推荐

