React Native中Base64转Blob后PDF损坏且大小异常
React Native中Base64转Blob导致PDF损坏的解决方案
问题根源
- MIME类型替换错误:直接用
replace('octet-stream', 'pdf')会破坏dataURL的结构,正确的PDF MIME类型是application/pdf,粗暴替换会导致Base64前缀格式异常,解码时出现数据偏差。 - 不必要的转码损耗:从S3获取的文件本身就是二进制数据,无需通过FileReader转成dataURL再转回Blob,多步转码容易触发React Native与浏览器的编码兼容问题。
- 二进制数组构造缺陷:
charCodeAt返回的数值可能超出字节范围,未做截断处理会导致Uint8Array数据错误。
修复方案
方案1:跳过Base64转码,直接复用原始二进制数据
这是最可靠的方式,彻底避免转码问题:
getDocumentFromS3(sub._id, DocumentTypes.tos).then(data => { if (data) { // 直接基于原始数据构造Blob(若data本身是Blob可直接使用) const blob = data instanceof Blob ? data : new Blob([data], { type: 'application/pdf' }); console.log('Blob大小:', Math.round(blob.size / 1024), 'KB'); // 直接使用blob进行后续上传操作 // setTosFile(blob); } else { console.log('Agreement not generated yet'); } });
方案2:正确修复Base64转Blob逻辑(若必须使用Base64中转)
// 修正后的Base64转Blob函数 const b64toFile = (b64Data, filename) => { const arr = b64Data.split(','); // 正确设置MIME类型前缀,避免粗暴替换 const correctedBase64 = `data:application/pdf;base64,${arr[1]}`; const bin = atob(arr[1]); const uint8Array = new Uint8Array(bin.length); for (let i = 0; i < bin.length; i++) { // 截断数值确保在字节范围内(0-255) uint8Array[i] = bin.charCodeAt(i) & 0xFF; } const blob = new Blob([uint8Array], { type: 'application/pdf' }); console.log('Blob大小:', Math.round(blob.size / 1024), 'KB'); return blob; }; // 修正后的S3获取逻辑 getDocumentFromS3(sub._id, DocumentTypes.tos).then(data => { if (data) { const reader = new FileReader(); reader.readAsDataURL(data); reader.onloadend = function () { const base64data = reader.result; const blob = b64toFile(base64data, 'tos.pdf'); setTosFile(blob); }; } else { console.log('Agreement not generated yet'); } });
关键注意事项
- React Native的
FileReader与浏览器实现存在细微差异,尽量减少不必要的Base64转码操作。 - 必须使用Base64时,严格遵循
data:application/pdf;base64,xxxx的格式规范,不要随意修改前缀。 - 处理二进制字符时,用
& 0xFF截断数值,确保每个元素都是合法的字节值。
内容的提问来源于stack exchange,提问作者Nikhil Kolte
相关产品推荐
相关产品推荐

