Expo React Native使用expo-file-system下载PDF格式无效如何解决
PDF下载后格式无效问题修复
核心错误原因
- axios请求PDF接口时未指定二进制响应类型,默认将PDF二进制流按UTF-8文本解析,原始数据被不可逆损坏
- 数据转码逻辑冗余错误:错误将接口返回的文本内容按base64解析后再次转base64,写入文件的内容不符合PDF格式规范
- 创建文件时未给文件名添加
.pdf后缀,部分系统PDF阅读器无法正确识别文件类型
修复步骤
- 给axios请求添加
responseType: 'arraybuffer'配置,确保拿到未被转码的原始PDF二进制数据 - 移除无效的重复转码逻辑,直接将ArrayBuffer格式的响应数据转成base64字符串
- 创建文件时给文件名追加
.pdf后缀,兼容系统文件识别规则
修正后代码
修正后的grabPdf方法
const grabPdf = async () => { axiosConfig.defaults.headers.common['Authorization'] = `Bearer ${user.token}`; const response = await axiosConfig('/user/invoice/C0F19758-0001/247', { // 关键配置:指定响应类型为二进制数组,避免文本转码损坏PDF responseType: 'arraybuffer' }).catch(error => { console.log('请求PDF失败: ', error.response?.data || error.message); alert('下载失败: ' + error.message); }); // 正确将二进制数据转换为base64 const pdfBuffer = Buffer.from(response.data); return pdfBuffer.toString('base64'); }
修正后的文件创建逻辑
在downloadFile方法中修改createFileAsync调用,补全文件后缀:
await StorageAccessFramework.createFileAsync( permissions.directoryUri, // 文件名追加.pdf后缀 `inv${payment.invoice_number}.pdf`, 'application/pdf' ).then(async(uri) => { await FileSystem.writeAsStringAsync(uri, pdf, { encoding: FileSystem.EncodingType.Base64 }); Alert.alert('Success', 'Successfully downloaded'); }).catch((e) => { console.log('写入文件失败: ', e); alert('保存文件失败'); });
有效性校验
修复后可以在返回base64字符串前打印前10个字符,合法PDF文件的base64开头固定为JVBERi0xLj(对应PDF文件头标识%PDF-1.x),如果开头不符合该特征,说明接口返回的数据本身有问题。
内容的提问来源于stack exchange,提问作者Vic Andam
相关产品推荐
相关产品推荐

