React Native用预签名URL传OSS遇403,Postman可正常上传
解决React Native 0.70中fetch上传阿里云OSS预签名URL返回403及图片损坏问题
核心问题分析
阿里云OSS的预签名URL校验严格,请求的头信息、请求体格式必须和生成预签名时的参数完全匹配。你遇到的403是因为fetch请求多带了Content-Type头(和预签名生成条件不匹配),而base64上传损坏是因为直接发送了base64字符串而非原始二进制数据。Postman成功的关键是关闭Content-Type头并上传原始二进制,这就是排查方向。
具体解决方案
1. 移除fetch请求中的Content-Type头
预签名生成时如果未指定Content-Type作为签名条件,前端请求绝对不能添加这个头,否则会触发签名校验失败返回403。
// 正确的fetch请求示例 const uploadImage = async (presignedUrl, fileUri) => { // 先获取原始二进制文件流(以react-native-blob-util为例) const blobResponse = await RNBlobUtil.fetch('GET', fileUri); const binaryData = blobResponse.data; const response = await fetch(presignedUrl, { method: 'PUT', headers: {}, // 不要设置任何Content-Type相关头 body: binaryData // 直接传原始二进制数据 }); if (response.ok) { console.log('上传成功'); } else { console.error('上传失败:', await response.text()); } };
2. 正确读取本地文件的二进制数据
使用react-native-blob-util时,要直接获取文件的原始二进制,避免转成base64或其他格式:
import RNBlobUtil from 'react-native-blob-util'; // 读取本地图片为二进制数据 const getBinaryFile = async (fileUri) => { const blob = await RNBlobUtil.fetch('GET', fileUri); return blob.data; // 这里返回的就是原始二进制Buffer };
3. 检查后端预签名生成逻辑
确认后端生成预签名URL时,没有将Content-Type加入签名参数。如果后端代码中指定了Content-Type(比如application/octet-stream),前端请求必须严格携带完全一致的头;如果后端未指定,前端一定不能加这个头。
4. 修复base64上传的图片损坏问题
如果必须使用base64上传,需要先将base64字符串转成原始二进制再发送,不能直接传base64文本:
// base64转二进制示例 const base64ToBinary = (base64Str) => { // 去掉base64前缀(如果有的话) const pureBase64 = base64Str.replace(/^data:image\/jpeg;base64,/, ''); // 转成Uint8Array二进制数据 return Uint8Array.from(atob(pureBase64), char => char.charCodeAt(0)); }; // 上传调用 const binaryData = base64ToBinary(yourBase64String); await fetch(presignedUrl, { method: 'PUT', headers: {}, body: binaryData });
内容的提问来源于stack exchange,提问作者user938363
相关产品推荐
相关产品推荐

