Node.js中PDFkit生成PDF后端正常但浏览器显示空白页问题
PDFkit生成PDF后端正常,浏览器打开空白的解决办法
问题场景
在Node.js环境下使用PDFkit生成包含“Hello world!”的PDF文件,后端本地生成的文件能正常打开,但前端请求后在浏览器中打开显示空白页。
相关代码
浏览器端代码
const getOrderPdf = async (): Promise<void> => { console.log(orderId); const response = await getOrderRaport(); console.log(response); const file = window.URL.createObjectURL( new Blob([response], { type: "application/pdf" }), ); window.open(file); };
服务端代码
export const getOrderRaport = async ( req: Request<{}, {}, {}>, res: Response, next: NextFunction, ) => { const pdfName = `order-raport-634320c8df6fad44f1dce4e8.pdf`; const pdfDoc = new PDFDocument(); res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', `inline; filename=${pdfName}`); pdfDoc.pipe(fs.createWriteStream("./order-raport-634320c8df6fad44f1dce4e8.pdf")) pdfDoc.text("Hello world!") pdfDoc.pipe(res) pdfDoc.end(); };
问题原因
- 服务端流式处理冲突:PDFkit的
pipe是流式顺序处理,先pipe到文件流再pipe到响应流,会导致响应流无法完整接收PDF数据。当pdfDoc.end()执行时,文件流优先完成写入,响应流未获取完整二进制内容。 - 前端响应解析错误:如果请求方法未设置
responseType: 'blob',会默认把二进制PDF数据解析为字符串,后续生成Blob时数据损坏,导致打开空白。
解决方案
1. 调整服务端代码
改用缓冲区收集PDF数据,再同时写入文件和响应,避免流式冲突:
import concat from 'concat-stream'; // 需要先安装concat-stream包 export const getOrderRaport = async ( req: Request<{}, {}, {}>, res: Response, next: NextFunction, ) => { const pdfName = `order-raport-634320c8df6fad44f1dce4e8.pdf`; const pdfDoc = new PDFDocument(); // 收集PDF二进制数据 pdfDoc.pipe(concat((data: Buffer) => { // 写入本地文件 fs.writeFile(`./${pdfName}`, data, (err) => { if (err) console.error(err); }); // 设置响应头并返回完整数据 res.setHeader('Content-Type', 'application/pdf'); res.setHeader('Content-Disposition', `inline; filename=${pdfName}`); res.send(data); })); pdfDoc.text("Hello world!"); pdfDoc.end(); };
2. 调整前端请求配置
确保请求时指定responseType: 'blob'(以axios为例):
// 假设getOrderRaport是axios请求 const getOrderRaport = () => { return axios.get('/your-api-path', { responseType: 'blob' // 关键配置,确保获取二进制数据 }); }; const getOrderPdf = async (): Promise<void> => { console.log(orderId); const response = await getOrderRaport(); const file = window.URL.createObjectURL(response.data); window.open(file); };
验证
修改后,后端生成的本地文件依然正常,前端请求打开的PDF可正常显示“Hello world!”内容。
内容的提问来源于stack exchange,提问作者Pentium3k
相关产品推荐
相关产品推荐

