使用Expo上传takePictureAsync图片至Digital Ocean Space后无法预览
问题描述
使用Expo的takePictureAsync拍摄图片后,通过签名PUT URL上传至Digital Ocean Spaces,文件上传成功且大小正常,但预览URL无法渲染图片。尝试移除data:image/png;base64前缀后仍未解决。
原代码:
const pictureResponse = await camera.current.takePictureAsync({ base64: true }); const spacesBase64 = `data:image/png;base64,${pictureResponse.base64}`; const spacesBuffer = Buffer.from(spacesBase64, "base64"); const spacesBlob = new Blob([spacesBuffer]); const spacesFile = new File([spacesBlob], "test.jpg", { type: "image/jpeg" }); fetch(`https://signedputurl.com`, { method: 'PUT', body: spacesFile });
问题原因及修复方案
- Base64解码错误:
pictureResponse.base64本身就是纯图片的Base64编码,添加data:image/png;base64前缀后,Buffer会把前缀也当作Base64内容解码,直接导致图片数据损坏。 - Expo环境Buffer兼容性问题:React Native/Expo里的
Buffer是polyfill实现,直接用它转Blob容易出问题,换成Uint8Array处理更可靠。 - 冗余的File转换:上传时不需要把Blob转成File,直接用Blob作为请求体即可,减少不必要的转换步骤。
修复后的代码:
const pictureResponse = await camera.current.takePictureAsync({ base64: true }); // 直接使用返回的纯base64数据,无需添加前缀 const base64Data = pictureResponse.base64; // 将base64转为Uint8Array,再生成对应格式的Blob const uint8Array = Uint8Array.from(atob(base64Data), char => char.charCodeAt(0)); const imageBlob = new Blob([uint8Array], { type: pictureResponse.type || 'image/jpeg' }); // 发起PUT请求上传Blob await fetch('https://signedputurl.com', { method: 'PUT', body: imageBlob, headers: { // 若签名URL限制了Content-Type,需与Blob的type保持一致 'Content-Type': pictureResponse.type || 'image/jpeg' } });
额外注意:
- 如果拍摄时指定了
format: 'png',要同步修改Blob的type为image/png,文件名也对应调整为.png。 - 确认签名PUT URL的配置是否允许对应的Content-Type,部分签名URL会限制上传的文件类型。
内容的提问来源于stack exchange,提问作者Schotsl
相关产品推荐
相关产品推荐

