React Native使用预签名URL上传图片到Amazon S3后文件损坏如何解决
问题根因
你使用S3预签名PUT URL上传时,错误使用了FormData封装文件:
- S3的预签名PUT接口会直接把整个请求体当成对象内容存储,不会解析
multipart/form-data格式 - 你用
FormData封装图片后,请求体里会额外带上form边界、字段名等文本内容,相当于把这些内容和图片二进制一起存成了文件,最终导致图片损坏 - 之前自有服务端可以正常使用,是因为你的服务端会主动解析
multipart/form-data格式,提取出文件字段的二进制内容;Insomnia测试时你直接上传图片二进制,没有额外的form封装,所以可以正常打开
修复方案
去掉FormData封装,直接上传图片的二进制内容即可,修改后的代码参考如下:
const result = await ImagePicker.launchCameraAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Images, allowsEditing: true, aspect: [1, 1], }); if (!result.cancelled) { const resizeResult = await ImageManipulator.manipulateAsync( result.uri, [{ resize: { height: 400, width: 400 } }], { format: "jpeg", compress: 0.8 } ); // 读取本地图片为Blob对象 const imageBlob = await fetch(resizeResult.uri).then(res => res.blob()); const config = { headers: { "Content-Type": "image/jpeg", // 如果生成预签名URL时要求单独传x-amz-acl头,这里加上即可 // "x-amz-acl": "public-read" }, }; // 直接传Blob作为请求体,不要用FormData axios.put(results.data, imageBlob, config) .then((res) => console.log(res)) .catch((e) => console.log(e.response)); }
其他注意事项
- 确保请求的
Content-Type和生成预签名URL时传入的Content-Type完全一致,否则会出现签名不匹配错误 - 如果axios传输Blob有兼容性问题,也可以换成
rn-fetch-blob库直接读取本地文件流上传,兼容性更好
内容的提问来源于stack exchange,提问作者yoann84
相关产品推荐
相关产品推荐

