前端将react-signature-canvas生成的base64转PNG上传S3文件损坏如何解决
核心错误原因
- S3 预签名 PUT 接口要求直接传入文件原始二进制流,你将 Blob 封装进 FormData 后,传输内容会附带表单分隔符、字段标识等额外信息,存储到 S3 的文件不是纯图片二进制,因此无法打开。
- 调用 PUT 接口上传时错误使用
application/json作为 Content-Type,S3 会将上传内容按 JSON 格式处理,同时会导致文件类型识别错误,出现后缀变为 json/html 的问题。 - 如果你提前删除了
toDataURL()返回结果的data:image/png;base64,前缀,fetch 方法无法识别该字符串为合法 dataURI,转换出的 Blob 本身就是错误内容。
修复后的代码
const fileUpload = async signatureImageSrc => { // 如果你之前删除了dataURL前缀,这里要先拼回来 const completeDataUrl = signatureImageSrc.startsWith('data:') ? signatureImageSrc : `data:image/png;base64,${signatureImageSrc}`; // 转换Blob时指定正确的MIME类型 const signatureImage = await (await fetch(completeDataUrl)).blob(); // 生成预签名URL的请求保持不变 const getUploadUrlConfig = { headers: { "Content-Type": "application/json" } }; const fileName = id + "-" + "signature.png"; const uploadUrlRes = await axios.post( "/upload_url", {fileName: fileName, fileType: "image/png"}, getUploadUrlConfig ); // 上传到S3的PUT请求单独配置头信息 const uploadToS3Config = { headers: { "Content-Type": "image/png" } }; // 直接传Blob作为请求体,不要封装FormData await axios.put(uploadUrlRes.data, signatureImage, uploadToS3Config); };
关键调整说明
- 保持 dataURL 的前缀完整,确保 fetch 可以正常转换为对应格式的 Blob
- 预签名 PUT 请求直接传递原始 Blob 作为请求体,不需要封装 FormData
- PUT 请求的 Content-Type 必须和生成预签名 URL 时提交的
fileType: "image/png"完全一致,否则S3会判定请求非法或存储错误的文件类型
内容的提问来源于stack exchange,提问作者Nickfis
相关产品推荐
相关产品推荐

