本文详解客户端 HTML 转 PDF 的完整配置、分页控制、Worker API 链式调用,以及跨域图片、Canvas 尺寸限制、CVE-2026-22787 XSS 漏洞修复等常见问题解决方案。

文章目录 **

你可能会问,鼠标右键就能打印网页,为什么还要自己编程实现这种需求。我的回答是:第一,做网页永远优先考虑移动端的体验;第二,需要精细化控制生成的PDF内容,而非打印整个HTML网页。

一、html2pdf.js 项目简介

html2pdf.js 是一个纯客户端 JavaScript 库,可将任意网页或 DOM 元素转换为可打印的 PDF 文档。它基于 html2canvas(负责将 HTML 渲染为 Canvas 图像)和 jsPDF(负责将图像封装为 PDF)构建,整个转换过程完全在浏览器中完成,无需服务器参与

核心定位:html2pdf.js 本质上是一个"截图式"PDF 生成器——它将 HTML 内容先渲染为位图图像,再将图像嵌入 PDF。这意味着输出的是栅格图像而非矢量文本,文字不可选中和搜索,且文件体积较大。

html2pdf.js 基本用法示例

最简单的用法只需一行代码:

var element = document.getElementById("element-to-print");
html2pdf(element);

这将生成 #element-to-print 的 PDF 并自动触发下载。

二、html2pdf.js 安装与引入

CDN 引入(推荐)

使用 cdnjs 锁定特定版本,确保稳定性:

<script
  src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"
  integrity="sha512-GsLlZN/3F2ErC5ifS5QtgpiJtWd43JWSuIgh7mbzZ8zBps+dvLusV+eNQATqgA/HdeKFVgA5v3S/cIrLF7QnIg=="
  crossorigin="anonymous"
  referrerpolicy="no-referrer"
></script>

直接下载

下载 dist/html2pdf.bundle.min.js 到项目目录:

<script src="html2pdf.bundle.min.js"></script>

npm 安装

npm install --save html2pdf.js
注意:包名必须包含 .js 后缀,即 html2pdf.js 而非 html2pdf

Bower 安装

bower install --save html2pdf.js

浏览器控制台临时使用

若无法修改页面源码,可在浏览器控制台中动态注入:

function addScript(url) {
  var script = document.createElement("script");
  script.type = "application/javascript";
  script.src = url;
  document.head.appendChild(script);
}
addScript(
  "https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js",
);

// 注入后即可使用
html2pdf(document.body);

非打包版本依赖顺序

若使用未打包的 dist/html2pdf.min.js,必须按顺序引入依赖,否则 jsPDF 内置的 html2canvas 会覆盖独立版本:

<script src="jspdf.min.js"></script>
<script src="html2canvas.min.js"></script>
<script src="html2pdf.min.js"></script>

三、html2pdf.js 使用场景与实战案例

github仓库:https://github.com/eKoopmans/html2pdf.js

场景 1:发票与报表导出

这是 html2pdf.js 最典型的应用场景。将页面中的发票或报表区域导出为 PDF。

function exportInvoice() {
  const element = document.getElementById("invoice");

  const opt = {
    margin: [10, 10, 10, 10], // 上下左右边距 10mm
    filename: `invoice-${Date.now()}.pdf`,
    image: { type: "jpeg", quality: 0.98 },
    html2canvas: {
      scale: 2, // 高清输出
      useCORS: true, // 允许跨域图片
      scrollX: 0,
      scrollY: 0,
    },
    jsPDF: {
      unit: "mm",
      format: "a4",
      orientation: "portrait",
    },
    pagebreak: {
      mode: ["css", "legacy"], // 尊重 CSS 分页规则
      avoid: ".no-break", // 避免在这些元素内分页
    },
  };

  html2pdf().set(opt).from(element).save();
}

场景 2:简历 / 证书 / 合同一键下载

利用 onclone 在导出前隐藏编辑按钮、添加水印等。

function exportResume() {
  const element = document.querySelector(".resume-container");

  const opt = {
    margin: 0,
    filename: "my-resume.pdf",
    image: { type: "jpeg", quality: 0.95 },
    html2canvas: { scale: 2 },
    jsPDF: { unit: "mm", format: "a4", orientation: "portrait" },
  };

  // 使用 Worker API 在生成后添加水印
  html2pdf()
    .set(opt)
    .from(element)
    .toPdf()
    .get("pdf")
    .then(function (pdf) {
      // 在每页添加页眉/页脚
      const totalPages = pdf.internal.getNumberOfPages();
      for (let i = 1; i <= totalPages; i++) {
        pdf.setPage(i);
        pdf.setFontSize(10);
        pdf.text("Confidential - Page " + i + " of " + totalPages, 10, 287);
      }
    })
    .save();
}

场景 3:长文档分页导出(避免内容截断)

继续阅读全文:https://blog.axiaoxin.com/post/html2pdf-guide/

标签: none

添加新评论