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

Node.js PDFKit如何传入HTML代码作为函数参数生成PDF

结论

PDFKit 没有内置可直接传入HTML代码并自动渲染对应内容的原生函数。
PDFKit本身是底层PDF生成库,核心API围绕基础绘制能力设计(文本、矢量图形、图片、基础样式设置),没有内置HTML解析、CSS样式计算、复杂排版(浮动、流式布局、表格等)的引擎,无法直接识别HTML标签规则完成渲染。


仅基于PDFKit的实现方案

如果不能引入额外的HTML转PDF第三方依赖,可以通过「HTML标签规则映射+手动调用PDFKit API」的方式实现简易HTML渲染,适合结构简单、标签范围可控的场景(比如基础富文本、简单文章内容),具体实现逻辑如下:

  • 第一步:确定需要支持的HTML标签范围,提前做好标签和PDFKit API的映射规则,比如:
    • 块级标签:<h1>~<h6>对应不同字号的加粗字体、段后间距;<p>对应正文字号、行间距;<br>对应换行;<li>对应缩进+列表标记
    • 行内标签:<b>/<strong>对应切换粗体;<i>/<em>对应切换斜体;<u>对应开启下划线;<font color="xxx">对应设置字体颜色
  • 第二步:编写轻量解析逻辑,把传入的HTML字符串拆分成带样式标记的内容块,不需要实现完整的HTML解析器,简单场景用正则替换、标签分割即可完成基础标签的识别。
  • 第三步:遍历解析后的内容块,根据每个块的样式标记,依次调用PDFKit的font()、fontSize()、fillColor()、text()、moveDown()等API完成绘制,利用PDFKit自带的文本自动换行、流式排版能力,不需要手动计算每行文本的坐标。

简易实现示例代码

const PDFDocument = require('pdfkit');
const blobStream = require('blob-stream');

/**
 * 基于PDFKit的简易HTML渲染方法
 * @param {PDFDocument} doc PDFKit实例
 * @param {string} html 待渲染的HTML字符串
 * @param {number} startX 内容起始X坐标
 * @param {number} startY 内容起始Y坐标
 */
function renderSimpleHtml(doc, html, startX = 100, startY = 100) {
  doc.x = startX;
  doc.y = startY;

  // 标签预处理,替换为自定义标记方便拆分
  let processed = html
    .replace(/<h1>(.*?)<\/h1>/gis, '\n[block:h1]$1[/block]\n')
    .replace(/<p>(.*?)<\/p>/gis, '\n[block:p]$1[/block]\n')
    .replace(/<br\s*\/?>/gis, '\n')
    .replace(/<b>(.*?)<\/b>/gis, '[style:b]$1[/style]')
    .replace(/<strong>(.*?)<\/strong>/gis, '[style:b]$1[/style]')
    .replace(/<i>(.*?)<\/i>/gis, '[style:i]$1[/style]')
    .replace(/<em>(.*?)<\/em>/gis, '[style:i]$1[/style]')
    .replace(/<u>(.*?)<\/u>/gis, '[style:u]$1[/style]');

  // 拆分内容块
  const blocks = processed.split('\n').filter(item => item.trim());
  blocks.forEach(block => {
    // 渲染一级标题
    if (block.startsWith('[block:h1]')) {
      const text = block.replace('[block:h1]', '').replace('[/block]', '').replace(/\[\/?style:[biu]\]/g, '');
      doc.font('Helvetica-Bold').fontSize(25).fillColor('#000').text(text, { continued: false });
      doc.moveDown(1);
      return;
    }
    // 渲染段落
    if (block.startsWith('[block:p]')) {
      let text = block.replace('[block:p]', '').replace('[/block]', '');
      // 识别行内样式
      const hasBold = /\[style:b\]/.test(text);
      const hasItalic = /\[style:i\]/.test(text);
      const hasUnderline = /\[style:u\]/.test(text);
      // 清理样式标记
      text = text.replace(/\[\/?style:[biu]\]/g, '');
      // 匹配对应字体
      let font = 'Helvetica';
      if (hasBold && hasItalic) font = 'Helvetica-BoldOblique';
      else if (hasBold) font = 'Helvetica-Bold';
      else if (hasItalic) font = 'Helvetica-Oblique';
      // 渲染段落
      doc.font(font).fontSize(12).fillColor('#333').text(text, {
        continued: false,
        lineGap: 4,
        underline: hasUnderline
      });
      doc.moveDown(0.5);
      return;
    }
    // 普通文本直接渲染
    doc.font('Helvetica').fontSize(12).fillColor('#333').text(block.replace(/\[\/?style:[biu]\]/g, ''));
  });
}

// 原有初始化逻辑
const doc = new PDFDocument();
const stream = doc.pipe(blobStream());

// 测试渲染HTML
const demoHtml = `
<h1>PDFKit渲染HTML测试</h1>
<p>这是普通正文内容,其中包含<b>加粗文本</b>、<i>斜体文本</i>、<u>下划线文本</u>,以及<b><i>同时加粗+斜体的文本</i></b>。</p>
<p>PDFKit会自动处理长文本换行,不需要手动计算每行宽度,段落之间会自动保留预设的间距。</p>
`;
renderSimpleHtml(doc, demoHtml);

doc.end();

方案说明

  • 上述示例只实现了最基础的标签支持,你可以根据业务需求扩展解析规则,比如支持列表、字体颜色、对齐方式、超链接、图片等标签,本质都是把HTML标签的表现,映射为PDFKit对应的API调用即可。
  • 该方案的局限性是无法兼容复杂HTML/CSS效果,比如浮动布局、Flex布局、复杂表格、嵌套层级极深的标签、外部引入的CSS规则等,这类复杂场景如果只靠手动映射规则开发成本会非常高;如果只是渲染简单富文本内容,该方案完全可以满足需求,且没有额外依赖。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 19:57:21