前端HTML转PDF的两种主流方案深度解析

前端 HTML 转 PDF 的两种主流方案深度解析(2026 年版)

目前前端生成 PDF 最主流的两种方案是:

  1. 客户端方案html2canvas + jsPDF(或其封装库 html2pdf.js
  2. 服务端方案Puppeteer / Playwright(Node.js 无头浏览器)

这两种方案几乎占据了 90% 以上的实际项目。下面从原理、优缺点、适用场景、核心代码、坑点与优化等维度进行深度对比。

一、核心对比表(快速决策)

维度客户端方案(html2canvas + jsPDF)服务端方案(Puppeteer / Playwright)胜出方
实现难度★☆☆☆☆(最简单)★★★☆☆(需后端)客户端
生成质量中等(样式丢失常见)极高(接近浏览器打印效果)服务端
中文/字体支持较差(需特殊处理)优秀(可加载本地字体)服务端
大文件 / 长页面容易卡顿、崩溃稳定服务端
分页控制弱(需 hack)强(支持 @page、页眉页脚)服务端
部署复杂度零(纯前端)中等(需 Node 服务)客户端
性能压力前端浏览器承担后端服务器承担看场景
安全性高(客户端)中(后端需注意 HTML 注入)客户端
2026 年推荐场景简单报表、导出预览、H5 小程序正式合同、发票、复杂报告、打印级 PDF

二、方案一:客户端 —— html2canvas + jsPDF(最常用)

原理
  1. html2canvas 把 DOM 元素渲染成 Canvas(像素级截图)
  2. jsPDF 把 Canvas 转为 PDF 文件并下载
推荐库
  • 直接用 html2pdf.js(封装版,最推荐)
  • 或手动组合 html2canvas + jsPDF
核心代码(Vue 3 + html2pdf.js)
<template> <div ref="content"> <!-- 你的 HTML 内容 --> <h1>发票标题</h1> <table>...</table> </div> <button @click="exportPDF">导出 PDF</button> </template> <script setup> import html2pdf from 'html2pdf.js' const content = ref(null) const exportPDF = () => { const opt = { margin: [10, 10, 10, 10], filename: 'report.pdf', image: { type: 'jpeg', quality: 0.98 }, html2canvas: { scale: 2, // 清晰度(2倍最合适) useCORS: true, // 跨域图片 letterRendering: true }, jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' } } html2pdf().set(opt).from(content.value).save() } </script> 
优点
  • 零后端,部署最简单
  • 适合 H5、小程序、内部工具
致命缺点(2026 年仍未彻底解决)
  • 复杂 CSS3(flex、grid、阴影、渐变)容易变形
  • 中文字体模糊或缺失
  • 超长页面容易内存溢出
  • 分页控制极差(经常出现表格断行、页眉页脚难处理)

优化技巧

  • 使用 scale: 2 提升清晰度
  • 提前把需要导出的内容克隆到一个隐藏的 div 中,专门优化样式
  • 对于表格推荐使用 jspdf-autotable 插件单独处理

三、方案二:服务端 —— Puppeteer / Playwright(质量之王)

原理

启动无头浏览器(Headless Chrome / Firefox / WebKit),加载完整 HTML 页面后,直接调用 page.pdf() 生成 PDF。

2026 年推荐:Playwright(已全面超越 Puppeteer)

Playwright 优势:多浏览器支持、自动等待、API 更现代、稳定性更高。

核心代码(Node.js + Express)
// pdfService.jsconst{ chromium }=require('playwright')asyncfunctionhtmlToPdf(htmlContent){const browser =await chromium.launch({headless:true})const page =await browser.newPage()// 关键:设置视口和打印样式await page.setContent(htmlContent,{waitUntil:'networkidle'})const pdfBuffer =await page.pdf({format:'A4',printBackground:true,margin:{top:'15mm',bottom:'15mm',left:'10mm',right:'10mm'},displayHeaderFooter:true,headerTemplate:'<div>页眉</div>',footerTemplate:'<div>第 <span></span> 页</div>'})await browser.close()return pdfBuffer }
前端调用示例
const res =awaitfetch('/api/export-pdf',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({html: document.getElementById('content').outerHTML })})const blob =await res.blob()const url =URL.createObjectURL(blob)const a = document.createElement('a') a.href = url a.download ='report.pdf' a.click()
优点
  • 生成效果几乎和浏览器打印一致
  • 原生支持 @pagepage-break-before/after 分页控制
  • 中文字体完美(可加载本地字体或系统字体)
  • 支持页眉页脚、加密、水印、目录等高级功能
缺点
  • 需要部署 Node 服务
  • 并发高时消耗服务器资源(可使用 puppeteer-cluster / playwright-cluster 做池化)

四、最终推荐(2026 年真实选择)

  • 推荐客户端方案:内部工具、简单报表、H5 活动页、快速 MVP
  • 强烈推荐服务端方案:合同、发票、正式报告、需要精确分页和美观样式的场景
  • 混合方案(最优解):前端负责编辑预览 + 服务端负责最终生成 PDF(目前大厂主流做法)

你现在要做的是哪类 PDF?

  • 简单数据报表?
  • 合同/发票类正式文件?
  • 还是需要页眉页脚 + 精确分页的复杂报告?

告诉我具体需求,我可以给你对应方案的最优完整代码模板。

Read more

Flutter 三方库 eth_sig_util 的鸿蒙化适配指南 - 掌握以太坊加密签名核心技术、助力鸿蒙端 Web3 钱包与去中心化身份验证应用开发

Flutter 三方库 eth_sig_util 的鸿蒙化适配指南 - 掌握以太坊加密签名核心技术、助力鸿蒙端 Web3 钱包与去中心化身份验证应用开发

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 eth_sig_util 的鸿蒙化适配指南 - 掌握以太坊加密签名核心技术、助力鸿蒙端 Web3 钱包与去中心化身份验证应用开发 前言 在 OpenHarmony 鸿蒙应用的 Web3 浪潮中,安全性是应用生死存亡的关键。无论是构建非托管钱包、登录去中心化应用(dApp),还是执行 EIP-712 结构化数据的确认,都离不开严谨的以太坊签名与加密协议。eth_sig_util 作为一个专门针对以太坊签名习惯优化的 Dart 工具库,支持 personal_sign、signTypedData 以及公钥恢复等核心算法。本文将指导你如何在鸿蒙端集成 eth_sig_util,构建一套符合全球标准的加密验证体系。 一、原原理分析 / 概念介绍 1.

NavRL实战:如何用PPO算法在NVIDIA Isaac Sim中训练无人机避障模型(附GitHub代码)

NavRL实战:如何用PPO算法在NVIDIA Isaac Sim中训练无人机避障模型(附GitHub代码) 无人机在复杂动态环境中的自主导航一直是工业界和学术界的研究热点。传统基于规则的方法在面对未知障碍物时往往表现不佳,而强化学习技术为解决这一问题提供了新思路。本文将手把手教你如何利用开源NavRL框架,在NVIDIA Isaac Sim环境中复现基于PPO算法的无人机避障模型训练过程。 1. 环境配置与基础准备 在开始训练前,我们需要搭建完整的开发环境。NavRL框架主要依赖NVIDIA Isaac Sim作为仿真平台,这是一个专为机器人学习设计的高性能模拟器。 硬件要求: * GPU:NVIDIA RTX 3060及以上(建议显存≥8GB) * 内存:32GB及以上 * 存储:至少50GB可用空间(用于存放仿真环境) 软件依赖安装: # 创建conda环境 conda create -n navrl python=3.8 conda activate navrl # 安装基础依赖 pip install torch==1.12.

基于Verilog的组合逻辑电路FPGA完整示例

从零开始:用Verilog在FPGA上实现一个真正的组合逻辑电路 你有没有过这样的经历?明明代码写得“很对”,仿真也跑通了,结果烧进FPGA后LED就是不亮——最后发现是因为某个 case 语句漏了个分支,综合器悄悄给你塞了个锁存器? 这正是无数初学者在FPGA开发中踩过的坑。而这一切的根源,往往就出在 组合逻辑电路设计 这个看似简单的起点上。 今天,我们就来彻底讲清楚一件事:如何用Verilog,在FPGA上正确、高效地实现一个纯粹的组合逻辑电路。不只是“能跑”,而是要 理解每一步背后的硬件行为 。 为什么组合逻辑是FPGA的“基本功”? 别看它名字普通,组合逻辑其实是整个数字系统设计的地基。 想象一下,你在做一个图像处理系统,每一帧有百万像素,每个像素都要做一次阈值判断。如果交给CPU逐个处理,早就卡死了;但如果你用组合逻辑把它做成并行电路——百万个比较器同时工作,一拍完成,这才是FPGA的真正威力。 它的核心特征非常明确: 输出只取决于当前输入,没有记忆,没有时钟驱动。 这意味着什么? - 它响应极快(仅受门延迟限制); - 它天然支持大规模并行; -

无人机双环PID悬停控制全解析

无人机双环PID悬停控制全解析

目录 1. 无人机悬停控制系统架构 2. 位置 PID 控制器设计 PID 结构体(扩展到位置控制) 3. 位置控制与姿态控制结合 位置数据结构 位置环 PID 初始化 4. 位置控制循环 5. 完整控制流程(位置 + 姿态 + 电机) 6. 传感器数据融合(GPS / 光流) GPS 数据读取示例 光流数据读取示例 7. 调试与优化建议 我们在之前的 姿态控制 PID 基础上,增加 位置控制 PID 层,这样无人机就可以根据 GPS 或 光流模块 提供的位置信息,实现精准悬停。 我会给你一个 完整的位置 + 姿态双环 PID