JavaScript 无原生 PDF 生成 API,需依赖 jsPDF(适合文字/简单图形)或 pdf-lib(适合修改现有 PDF);浏览器中通过 Blob + URL.createObjectURL 预览,复杂场景应交由后端如 puppeteer 处理。

JavaScript 本身没有原生 API 生成 PDF,必须依赖第三方库;浏览器环境无法直接写文件系统,所有“生成 PDF”实际是生成二进制 Blob 并触发下载或嵌入预览。
用 jsPDF 生成基础 PDF 文档
jsPDF 是最轻量、兼容性最好的选择,适合文字+简单图形场景。注意它不解析 HTML,html() 方法需配合 html2canvas 才能转 DOM,且性能差、样式支持有限。
- 安装:
npm install jspdf(ESM)或通过 CDN 加载https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js - 创建 A4 纵向 PDF:
const doc = new jspdf.jsPDF({ orientation: 'portrait', unit: 'mm', format: 'a4' }); - 添加文本(坐标单位默认 mm,原点在左上角):
doc.text('Hello World', 20, 30); - 导出为 Blob 并下载:
doc.save('document.pdf');(会触发浏览器下载) - 若需获取 Blob 对象而非立即下载:
const blob = doc.output('blob');
用 pdf-lib 修改已有 PDF 或插入动态内容
pdf-lib 不渲染页面,只操作 PDF 结构,适合填表、签名、合并、加水印等后端或前端高级操作。它不能从零画图,但可加载现有 PDF 并修改字段、插入图像、追加页。
- 加载已有 PDF:
const pdfDoc = await PDFDocument.load(existingPdfBytes); - 填充表单字段(需 PDF 原本含 AcroForm):
const form = pdfDoc.getForm(); const field = form.getTextField('name'); field.setText('Alice'); - 插入 PNG/JPEG 图像(需先
pdfDoc.embedPng()或embedJpg()):const image = await pdfDoc.embedPng(pngBytes); page.drawImage(image, { x: 50, y: 50, width: 100 }); - 保存变更:
const bytes = await pdfDoc.save();(返回 Uint8Array)
浏览器中预览 PDF 而不下载
直接用 URL.createObjectURL() 创建临时 URL,再交由 或 渲染。不要用 window.open(),部分浏览器会拦截。
立即学习“Java免费学习笔记(深入)”;
- 假设
pdfBytes是Uint8Array或Blob:const blob = new Blob([pdfBytes], { type: 'application/pdf' }); const url = URL.createObjectURL(blob); - 插入到页面:
document.getElementById('pdf-viewer').src = url;(对应) - 记得在不再需要时释放内存:
URL.revokeObjectURL(url);(尤其在频繁生成时) - 注意:Safari 对
iframe中的 PDF 渲染有缓存 bug,可加时间戳参数绕过:url + '?t=' + Date.now()
服务端生成 PDF 的更可靠方案
前端生成 PDF 在复杂排版、中文字体、页眉页脚、分页控制上非常脆弱。真正稳定的做法是把数据发给后端,用 Node.js 的 pdfmake、puppeteer(渲染 HTML 为 PDF)或 Python 的 weasyprint 处理。
-
puppeteer最接近“所见即所得”:await page.goto('data:text/html,' + encodeURIComponent(html), { waitUntil: 'networkidle0' }); const pdf = await page.pdf({ format: 'A4' }); - 字体问题最常导致中文乱码——
puppeteer需显式指定字体路径;pdfmake需提前注册ttf字体对象 - 避免在前端拼接大量 HTML 再传给后端:体积大、XSS 风险高、服务端解析负担重。应只传结构化数据(如 JSON),由后端模板组装
PDF 生成不是“调一个函数就完事”的事情,字体嵌入、分页逻辑、表单交互、打印适配这些环节,任何一个没对齐都会导致用户打不开或内容错位。别迷信“纯前端一键生成”,先想清楚你到底要的是“能看就行的快照”,还是“能归档签字的正式文档”。











