Node.js中通过JSON发送PDF文件应采用何种数组格式?
选择PDF在JSON响应中的传输格式:Base64 vs 数字数组
嘿,针对你用Express开发Node.js API、要把AWS上的PDF返回成JSON的场景,我来帮你拆解下几种格式的优劣,结合你的需求给出最适合的方案~
先明确你的核心约束
- PDF文件不超过200kb,响应大小和速度不是问题
- 必须返回JSON格式(所以直接返回二进制PDF响应的方案就不考虑了)
可选格式分析
1. Base64字符串(最推荐)
这是JSON中传输二进制数据最常用的方案,优势非常明显:
- 原生兼容JSON:字符串是JSON的基础类型,不需要任何特殊处理就能序列化/反序列化,后端和前端都不容易出问题
- 前端处理简单:不管是浏览器还是Node.js前端,都有成熟的方法把Base64转成Blob/Buffer,直接用于显示或保存PDF
- 可读性尚可:至少是一串可识别的字符,比一堆数字数组更容易调试
唯一的“缺点”是体积会比原二进制大33%左右——但你的PDF最多200kb,转成Base64也就266kb,完全在你的可接受范围内(毕竟你说响应大小速度不是问题)。
后端实现示例(Express + AWS SDK v3)
const { S3Client, GetObjectCommand } = require("@aws-sdk/client-s3"); const express = require('express'); const app = express(); const s3Client = new S3Client({ region: '你的AWS区域' }); // 工具函数:将S3返回的流转成Buffer const streamToBuffer = (stream) => new Promise((resolve, reject) => { const chunks = []; stream.on('data', chunk => chunks.push(chunk)); stream.on('end', () => resolve(Buffer.concat(chunks))); stream.on('error', reject); }); app.get('/api/pdf/:id', async (req, res) => { const { id } = req.params; try { // 从S3获取PDF文件 const s3Response = await s3Client.send(new GetObjectCommand({ Bucket: '你的S3桶名', Key: `pdfs/${id}.pdf` // 假设PDF在S3中的存储路径 })); const pdfBuffer = await streamToBuffer(s3Response.Body); // 转成Base64字符串 const pdfBase64 = pdfBuffer.toString('base64'); res.json({ ID: id, pdf: pdfBase64 }); } catch (err) { console.error('获取PDF失败:', err); res.status(500).json({ error: 'Failed to retrieve PDF' }); } }); app.listen(3000, () => console.log('API服务启动在3000端口'));
前端处理示例(浏览器环境)
async function loadAndOpenPDF(id) { const res = await fetch(`/api/pdf/${id}`); const data = await res.json(); // 将Base64转成Blob,用于显示或下载 const pdfBlob = new Blob( [Uint8Array.from(atob(data.pdf), c => c.charCodeAt(0))], { type: 'application/pdf' } ); // 生成临时URL打开PDF const pdfUrl = URL.createObjectURL(pdfBlob); window.open(pdfUrl); }
2. Uint8数组/普通数字数组
也就是你示例里的[21, 23, 34, 46, ...]这种格式:
- 体积和原二进制一致:没有Base64的33%膨胀,但实际上JSON里存储数字数组的字符数可能和Base64差不多(比如一个字节是0-255,转成数字字符串是1-3位,平均下来字符数接近Base64)
- 前端处理稍繁琐:需要把数字数组重新转成Uint8Array再生成Blob,步骤比Base64多一步
后端实现差异
把转Base64的代码改成:
const pdfArray = Array.from(new Uint8Array(pdfBuffer)); res.json({ ID: id, pdf: pdfArray });
前端处理差异
const pdfBlob = new Blob([new Uint8Array(data.pdf)], { type: 'application/pdf' });
最终推荐
结合你的需求(响应大小速度无压力),优先选择Base64字符串。它的实现成本最低,兼容性最好,前端处理的代码也更通用,不容易踩坑。
如果某天你的PDF体积变大,或者对响应大小有极致要求,再考虑切换到数字数组——但目前完全没必要。
内容的提问来源于stack exchange,提问作者Jaka Tertinek




