You need to enable JavaScript to run this app. 如何配合使用html-pdf与jsZip将生成的PDF写入压缩包?
优惠活动
大模型
产品
解决方案
定价
更多

如何配合使用html-pdf与jsZip将生成的PDF写入压缩包?

跑不通的核心原因

你之前的写法zip.file('newPDF.pdf', pdf.create(html).toStream())存在两个本质问题,根本没法拿到正确的PDF数据:

  • html-pdf的toStream()是带回调的异步方法,自身不会返回可读流实例,只会把生成的PDF流作为回调函数的入参传给你,你直接拿这个方法的调用返回值(一般是undefined)塞给zip.file(),自然传不进去任何有效数据
  • 就算你拿到了实际的流实例,JSZip虽然支持把可读流作为文件内容传入,也需要匹配对应的配置,否则会出现流还没读完、压缩包已经开始生成的时序问题,最终产出损坏的文件

正确实现方案

方案1:基于toStream的流写入(贴合你之前参考的示例写法)

按照html-pdf的原生回调语法,在回调内拿到真正的PDF流,再传给JSZip:

const pdf = require('html-pdf');
const JSZip = require('jszip');
const fs = require('fs');

const zip = new JSZip();
const htmlContent = '<p>需要转成PDF的HTML内容</p>';

// 严格遵循html-pdf的toStream回调语法
pdf.create(htmlContent).toStream((err, pdfReadableStream) => {
  if (err) throw err;
  
  // 拿到真实的PDF可读流后,直接作为文件内容传给zip
  zip.file('newPDF.pdf', pdfReadableStream);

  // 注意:生成zip流时必须开启streamFiles配置,否则无法正确消费传入的可读流
  zip.generateNodeStream({
    type: 'nodebuffer',
    streamFiles: true
  }).pipe(fs.createWriteStream('output.zip'))
  .on('finish', () => {
    console.log('压缩包生成完成');
  });
});

方案2:基于Buffer的写入(更稳定,无流时序问题)

实际开发中更推荐这种方式,避开流传递容易出现的时序、阻塞问题,直接用html-pdf自带的toBuffer方法拿到完整的PDF二进制内容,再写入压缩包:

pdf.create(htmlContent).toBuffer((err, pdfBuffer) => {
  if (err) throw err;
  
  // Buffer是同步可用的,写入zip不会有时序问题
  zip.file('newPDF.pdf', pdfBuffer);

  // 后续生成zip的逻辑和上面一致
  zip.generateNodeStream({ type: 'nodebuffer' })
    .pipe(fs.createWriteStream('output.zip'));
});

常见踩坑提醒

  • 绝对不要把pdf.create(html).toStream()的直接返回值传给JSZip,这个方法本身没有返回值,所有数据都在回调里
  • 用可读流传参给JSZip时,生成压缩包必须加streamFiles: true配置,否则JSZip会等所有流全部读完才会开始生成包,大文件场景下会占满内存,甚至出现文件内容为空的问题
  • html-pdf是纯Node.js端的包,没法直接在浏览器端环境运行,如果是前端场景需要换用适配浏览器的PDF生成库

内容的提问来源于stack exchange,提问作者Cl0ser

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.24 07:54:01