Node.js后端通过axios获取HTTP返回的PDF并正确保存到文件系统的方法
问题原因
你存出来的PDF损坏、打开空白,核心是两个配置错误:
- axios默认会把响应内容按UTF-8字符串解析,PDF里包含大量压缩后的非文本二进制字节(就是你看到的那段乱码流),字符串转码过程会直接篡改这些字节的原始值,写出来的文件结构自然就坏了。
- Blob是浏览器端的API,Node.js服务端没有适配服务端场景的Blob原生处理逻辑,硬套浏览器端的写法必然出问题。
另外你不用手动解析贴出来的那些PDF结构,%PDF-1.3头、对象块、Widths数组、FlateDecode压缩流都是标准PDF的固有结构,你看到的结构重复本质是字节被转码破坏后,用文本方式查看内容出现的错位,不是接口返回了重复内容。只要保证原始字节一个不差写到本地,PDF阅读器自己就能正常解析。
正确实现方案
核心逻辑只有一个:发请求的时候告诉axios不要做字符串转码,直接返回原始二进制数据,再原封不动写到文件里即可。根据PDF体积选对应写法:
小体积PDF(100MB以内)用ArrayBuffer
const axios = require('axios'); const fs = require('fs/promises'); async function downloadPdf(apiUrl, saveFilePath) { const res = await axios.get(apiUrl, { responseType: 'arraybuffer', // 最核心配置,缺失必然导致文件损坏 // 接口需要的鉴权、请求参数正常追加在这里即可 // headers: { Authorization: 'Bearer xxx' }, // params: { fileId: 123 } }); // 直接写入二进制缓冲,不要做toString、转Base64、转Blob之类的多余操作 await fs.writeFile(saveFilePath, res.data); } // 调用示例 downloadPdf('你的PDF接口请求地址', './本地存储路径/result.pdf')
大体积PDF用流写入,降低内存占用
如果PDF体积超过100MB,用ArrayBuffer会把整个文件加载到内存占用资源,直接用流的方式边接收边写入:
const axios = require('axios'); const fs = require('fs'); const { pipeline } = require('stream/promises'); async function downloadLargePdf(apiUrl, saveFilePath) { const res = await axios.get(apiUrl, { responseType: 'stream' }); // 管道自动处理背压、错误捕获,接收完数据自动关闭文件流 await pipeline(res.data, fs.createWriteStream(saveFilePath)); }
故障排查点
如果按上述写法保存后文件还是打不开,依次检查:
- 打印响应头的
content-type字段,如果不是application/pdf,说明接口返回的根本不是PDF内容,可能是报错的JSON、HTML鉴权页,自然无法作为PDF打开。 - 不要对拿到的二进制数据做任何编码转换、字符串拼接处理,哪怕你看到内容里包含可读的PDF结构文本,修改编码就会破坏字节完整性。
- 下载保存场景不需要引入任何第三方PDF解析/处理库,本质就是纯字节拷贝操作,多余的库反而会增加转码损坏的概率。
内容的提问来源于stack exchange,提问作者Kevin Lewis
相关产品推荐
相关产品推荐

