You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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();
};

问题原因

  1. 服务端流式处理冲突:PDFkit的pipe是流式顺序处理,先pipe到文件流再pipe到响应流,会导致响应流无法完整接收PDF数据。当pdfDoc.end()执行时,文件流优先完成写入,响应流未获取完整二进制内容。
  2. 前端响应解析错误:如果请求方法未设置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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 22:55:48