0

0

js 如何生成PDF文档

月夜之吻

月夜之吻

发布时间:2025-08-15 14:01:01

|

844人浏览过

|

来源于php中文网

原创

前端生成pdf主要依赖jspdf和html2canvas库的组合。1. 使用jspdf可编程创建pdf,适合结构化文档,能精确控制文本、图形、图片等元素;2. 结合html2canvas可将html内容转为canvas图片,再由jspdf嵌入pdf,实现复杂样式“所见即所得”导出,但文本不可选。该方案减轻服务器负担、提升用户体验、支持离线操作,适用于报告下载、证书生成、打印预览等场景。需注意性能优化(如简化dom、压缩图片、合理设置scale)、字体嵌入以保证跨设备一致性,以及处理跨域图片和css兼容性问题,确保多浏览器正常渲染。

js 如何生成PDF文档

JavaScript在浏览器端生成PDF文档,主要依赖于第三方库,其中最常用且功能强大的当属

jsPDF
html2canvas
的组合。它们允许你直接在客户端创建、编辑PDF,或者将现有的HTML内容转换为PDF格式,省去了服务器端的处理负担。

解决方案

要在JavaScript中生成PDF文档,通常有两种主要路径:一是通过编程方式直接构建PDF内容(比如添加文本、图片、形状),这主要由

jsPDF
这类库完成;二是将现有的HTML/CSS内容渲染成图片,再将图片嵌入到PDF中,这通常需要
html2canvas
jsPDF
协同工作。

1. 使用jsPDF直接构建PDF

这种方式适合生成结构化、数据驱动的文档,例如发票、报告摘要等。你可以精确控制每个元素的定位和样式。

// 引入jsPDF库
// 

const { jsPDF } = window.jspdf;

function generateSimplePdf() {
    const doc = new jsPDF();

    doc.setFont("helvetica", "bold");
    doc.setFontSize(22);
    doc.text("我的第一个PDF文档", 10, 20); // x, y 坐标

    doc.setFont("helvetica", "normal");
    doc.setFontSize(12);
    doc.text("这是通过jsPDF直接生成的文本内容。", 10, 40);
    doc.text("你可以添加多行文本,或者调整字体、颜色等。", 10, 50);

    // 添加一个矩形
    doc.setDrawColor(0, 0, 255); // RGB 蓝色
    doc.rect(10, 60, 50, 20); // x, y, width, height

    // 添加图片(需要图片数据或URL)
    // doc.addImage(imageData, 'JPEG', 10, 90, 50, 50);

    doc.save("简单示例.pdf");
}

// 调用函数生成PDF
// generateSimplePdf();

2. 使用html2canvas结合jsPDF将HTML转换为PDF

这种方法更适合将复杂的网页布局、图表、CSS样式等“截图”并保存为PDF。

html2canvas
会将指定的HTML元素渲染成一个Canvas图片,然后
jsPDF
再将这个Canvas图片添加到PDF中。

// 引入html2canvas和jsPDF
// 
// 

const { jsPDF } = window.jspdf;

async function generateHtmlToPdf() {
    const input = document.getElementById('contentToPrint'); // 假设你有一个ID为'contentToPrint'的HTML元素

    if (!input) {
        console.error("找不到ID为'contentToPrint'的元素。");
        return;
    }

    // 使用html2canvas将HTML元素渲染成Canvas
    const canvas = await html2canvas(input, {
        scale: 2, // 提高分辨率,让PDF更清晰
        useCORS: true // 如果有跨域图片,需要设置为true
    });

    const imgData = canvas.toDataURL('image/png');
    const pdf = new jsPDF('p', 'mm', 'a4'); // 'p'代表纵向,'mm'代表单位毫米,'a4'代表A4纸张大小

    const imgWidth = 210; // A4宽度为210mm
    const pageHeight = 297; // A4高度为297mm
    const imgHeight = canvas.height * imgWidth / canvas.width;
    let heightLeft = imgHeight;

    let position = 0;

    // 如果内容超过一页,则分页
    pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
    heightLeft -= pageHeight;

    while (heightLeft >= 0) {
        position = heightLeft - imgHeight;
        pdf.addPage();
        pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
        heightLeft -= pageHeight;
    }

    pdf.save("我的网页内容.pdf");
}

// 假设HTML结构:
/*

这是一个标题

这是一段示例文本,用来展示如何将HTML内容转换为PDF。你可以放入更复杂的布局,比如表格、图片和各种CSS样式。

  • 列表项1
  • 列表项2
  • 列表项3
@@##@@

这段文字是蓝色的加粗文本。

*/

前端生成PDF的常见场景与优势

在我看来,前端直接生成PDF这事儿,核心价值在于它能让用户体验更流畅、服务器压力更小。我个人觉得,这简直是前端工程师的“小魔法”之一。

那么,具体在哪些场景下我们会用到它呢?

  • 在线报告或账单下载: 用户在网站上查看完自己的消费记录或报表后,直接点击一个按钮就能下载PDF版本,无需等待服务器响应,体验感极佳。
  • 证书或凭证生成: 比如在线学习平台,用户完成课程后,即时生成并下载带有其姓名的结业证书。这比后台生成再推送到前端要快得多。
  • 打印预览功能: 很多在线编辑器或设计工具需要提供打印预览,前端生成PDF就能完美模拟打印效果,让用户所见即所得。
  • 数据导出: 将表格数据、图表直接导出为PDF格式,方便离线查看或分享。
  • 离线应用支持: 如果你的应用需要支持离线模式,那么在客户端生成PDF就显得尤为重要,因为没有服务器可以依赖。

它的优势是显而易见的:

  • 减轻服务器负担: PDF生成是个计算密集型任务,放在客户端处理,能显著减少服务器的CPU和内存消耗,尤其在高并发场景下,这简直是救命稻草。
  • 提升用户体验: 几乎是瞬时响应,用户不需要等待网络请求和服务器处理,下载体验更流畅。
  • 实时预览与交互: 可以在生成PDF前,根据用户的选择或输入,实时调整PDF内容和样式,提供更灵活的交互。
  • 技术栈统一: 对于前端团队来说,使用JavaScript生成PDF,避免了引入新的后端技术栈,维护成本更低。

当然,它也有自己的局限性,比如字体、复杂布局的兼容性问题,以及大文件生成时的性能挑战,这些都是我们做技术选型时需要深思熟虑的。

jsPDF和html2canvas:前端PDF生成的两大利器如何协同工作?

说起前端PDF生成,

jsPDF
html2canvas
这对搭档,简直是不可或缺的组合。它们各自有专长,又能在关键时刻互相补位,构建出强大的PDF生成能力。

jsPDF:PDF内容的“画笔”与“画布”

jsPDF
更像是一个底层的PDF API。它提供了一系列的函数,让你能像在画布上作画一样,一点点地“画”出PDF的内容。你可以:

iSlide PPT
iSlide PPT

DeepSeek AI加持,输入主题生成专业PPT,支持Word/PDF等45种文档导入,职场汇报、教学提案轻松搞定

下载
  • 精确控制文本: 设置字体、字号、颜色、对齐方式,甚至文本的旋转和缩放。我个人在做一些固定格式的报告时,特别喜欢用它来控制标题和数据表格的对齐,那种像素级的精准感让人很满足。
  • 绘制图形: 矩形、圆形、线条,甚至是自定义路径,都能轻松绘制。
  • 嵌入图片: 支持多种图片格式,可以指定图片的位置和大小。
  • 管理页面: 添加新页面,设置页眉页脚。

优点: 对PDF内容有极高的控制力,生成的文件通常体积较小,文本是可选择和搜索的(除非你嵌入的是图片)。适合生成结构化、数据驱动的文档。

缺点: 最大的痛点是,如果你想把一个复杂的HTML页面(比如包含大量CSS样式、复杂的DIV布局)转换成PDF,用

jsPDF
手动去“画”这些元素,那简直是噩梦。它不理解HTML和CSS的语义,你需要自己计算每个元素的坐标和大小,非常繁琐。

html2canvas:HTML内容的“快照”

html2canvas
则完全是另一种思路。它不会去理解PDF的结构,它的任务只有一个:把DOM元素渲染成一个Canvas图片。你可以把它想象成一个高级的“截图”工具。它会解析HTML和CSS,然后把这些视觉效果绘制到一个HTML
元素上。

优点: 完美保留了HTML/CSS的复杂布局和样式。你不需要关心元素的位置和样式,

html2canvas
会帮你搞定。这对于那些设计感很强的报告页面、或者需要原样输出网页内容的场景来说,简直是神来之笔。

缺点: 它生成的是一张图片。这意味着PDF中的文本不可选择、不可搜索,也无法复制。如果你的HTML内容非常大或者非常复杂,生成Canvas的过程可能会很慢,甚至内存溢出。而且,它对CSS的支持并非100%完美,一些复杂的CSS3特性(比如某些伪类、混合模式)可能渲染不出来。我遇到过几次因为

box-shadow
flexbox
布局在不同浏览器下渲染效果不一致,导致
html2canvas
输出有偏差的情况,调试起来还挺头疼的。

它们如何协同工作?

这才是关键!当你想把一个漂亮的HTML页面转换成PDF,同时又想利用

jsPDF
来管理PDF文档本身(比如设置页边距、添加页码、保存文件)时,它们就联手了。

  1. html2canvas
    负责渲染HTML:
    你指定一个HTML元素(比如一个
    div
    ),
    html2canvas
    会把它“拍”成一张高清的Canvas图片。
  2. jsPDF
    负责承载图片:
    jsPDF
    创建一个新的PDF文档,然后把
    html2canvas
    生成的Canvas图片作为一张大图,插入到PDF页面中。如果图片内容太长,超过一页,
    jsPDF
    还能帮你自动分页。

这种组合方式,既利用了

html2canvas
对HTML/CSS布局的强大渲染能力,又利用了
jsPDF
对PDF文档本身的控制能力,实现了“所见即所得”的PDF导出功能。当然,你得接受文本不可选这个权衡。

提升JavaScript PDF生成效率与跨浏览器兼容性的实用策略

在实际项目中,尤其当PDF内容复杂或数量较多时,生成效率和兼容性问题就会浮出水面。我发现,很多时候,一些小细节处理不好,就会导致用户体验直线下降,甚至出现各种奇奇怪怪的渲染问题。

1. 优化性能:

  • 精简HTML结构:
    html2canvas
    在处理DOM时,越复杂的DOM树消耗的资源越多。尽量减少不必要的嵌套、移除隐藏元素、合并简单的CSS规则。我通常会创建一个专门用于打印的HTML模板,比展示用的页面要简洁得多。
  • 图片优化: 如果HTML中包含大量图片,确保它们已经经过压缩,并且尺寸合理。
    html2canvas
    在处理大尺寸图片时会消耗大量内存。如果可能,提前将图片转换为Base64编码,减少网络请求。
  • 异步处理与进度反馈: PDF生成尤其是
    html2canvas
    渲染过程是同步且耗时的,这会阻塞主线程。务必使用
    async/await
    来处理,并在生成过程中给用户一个明确的加载提示(比如一个旋转的加载图标),避免用户以为页面卡死。
  • html2canvas
    scale
    参数:
    适当提高
    scale
    值可以生成更清晰的PDF,但也会增加渲染时间和内存消耗。根据实际需求找到一个平衡点。我一般会设置
    scale: 2
    3
    ,兼顾清晰度和性能。
  • 避免不必要的CSS属性:
    html2canvas
    对所有CSS属性的支持程度不一,一些复杂的CSS3动画、阴影、渐变、
    filter
    等可能会导致渲染缓慢或不准确。尽量使用更简单的CSS布局和样式。

2. 提升兼容性:

  • 字体嵌入(Font Embedding): 这是PDF兼容性的一个大坑。如果PDF中使用的字体在用户设备上不存在,或者没有正确嵌入到PDF中,那么文档打开时就会出现乱码或默认字体替换,导致排版混乱。
    jsPDF
    允许你加载和嵌入自定义字体(
    .ttf
    格式),这对于确保PDF在任何设备上都显示一致至关重要。你需要将字体文件转换为
    jsPDF
    支持的格式(通常是Base64编码的JS文件),然后通过
    doc.addFont()
    方法引入。
  • 跨浏览器测试:
    html2canvas
    的渲染效果在不同浏览器(Chrome, Firefox, Safari, Edge)之间可能存在细微差异,尤其是在处理复杂的CSS布局时。务必在主流浏览器中进行充分测试。
  • CSS兼容性: 了解
    html2canvas
    对CSS的支持限制。例如,它对
    position: fixed
    transform
    flexbox
    grid
    等布局的支持有时不尽如人意,或者需要特定的版本才能良好支持。遇到问题时,尝试用更传统的布局方式(如
    float
    display: block
    )来替代,或者对问题区域进行特殊处理。
  • 图片跨域问题: 如果HTML中包含来自不同域的图片,
    html2canvas
    在渲染时会遇到跨域安全限制。确保图片服务器配置了CORS,或者将图片转换为Base64编码直接嵌入HTML。
  • SVG支持:
    html2canvas
    对SVG的支持也在不断完善,但复杂的SVG可能无法完美渲染。如果SVG是关键内容,可以考虑将其预处理为图片格式再嵌入。

在实践中,我通常会建议为要生成PDF的HTML内容创建一个独立的、简洁的CSS文件,专门用于打印样式,这样可以避免很多不必要的渲染复杂性和兼容性问题。同时,充分的测试和对库的深入理解,是解决这些挑战的关键。

占位图

相关专题

更多
js获取数组长度的方法
js获取数组长度的方法

在js中,可以利用array对象的length属性来获取数组长度,该属性可设置或返回数组中元素的数目,只需要使用“array.length”语句即可返回表示数组对象的元素个数的数值,也就是长度值。php中文网还提供JavaScript数组的相关下载、相关课程等内容,供大家免费下载使用。

556

2023.06.20

js刷新当前页面
js刷新当前页面

js刷新当前页面的方法:1、reload方法,该方法强迫浏览器刷新当前页面,语法为“location.reload([bForceGet]) ”;2、replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,不能通过“前进”和“后退”来访问已经被替换的URL,语法为“location.replace(URL) ”。php中文网为大家带来了js刷新当前页面的相关知识、以及相关文章等内容

374

2023.07.04

js四舍五入
js四舍五入

js四舍五入的方法:1、tofixed方法,可把 Number 四舍五入为指定小数位数的数字;2、round() 方法,可把一个数字舍入为最接近的整数。php中文网为大家带来了js四舍五入的相关知识、以及相关文章等内容

754

2023.07.04

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

477

2023.09.01

JavaScript转义字符
JavaScript转义字符

JavaScript中的转义字符是反斜杠和引号,可以在字符串中表示特殊字符或改变字符的含义。本专题为大家提供转义字符相关的文章、下载、课程内容,供大家免费下载体验。

434

2023.09.04

js生成随机数的方法
js生成随机数的方法

js生成随机数的方法有:1、使用random函数生成0-1之间的随机数;2、使用random函数和特定范围来生成随机整数;3、使用random函数和round函数生成0-99之间的随机整数;4、使用random函数和其他函数生成更复杂的随机数;5、使用random函数和其他函数生成范围内的随机小数;6、使用random函数和其他函数生成范围内的随机整数或小数。

1011

2023.09.04

如何启用JavaScript
如何启用JavaScript

JavaScript启用方法有内联脚本、内部脚本、外部脚本和异步加载。详细介绍:1、内联脚本是将JavaScript代码直接嵌入到HTML标签中;2、内部脚本是将JavaScript代码放置在HTML文件的`<script>`标签中;3、外部脚本是将JavaScript代码放置在一个独立的文件;4、外部脚本是将JavaScript代码放置在一个独立的文件。

658

2023.09.12

Js中Symbol类详解
Js中Symbol类详解

javascript中的Symbol数据类型是一种基本数据类型,用于表示独一无二的值。Symbol的特点:1、独一无二,每个Symbol值都是唯一的,不会与其他任何值相等;2、不可变性,Symbol值一旦创建,就不能修改或者重新赋值;3、隐藏性,Symbol值不会被隐式转换为其他类型;4、无法枚举,Symbol值作为对象的属性名时,默认是不可枚举的。

553

2023.09.20

Java JVM 原理与性能调优实战
Java JVM 原理与性能调优实战

本专题系统讲解 Java 虚拟机(JVM)的核心工作原理与性能调优方法,包括 JVM 内存结构、对象创建与回收流程、垃圾回收器(Serial、CMS、G1、ZGC)对比分析、常见内存泄漏与性能瓶颈排查,以及 JVM 参数调优与监控工具(jstat、jmap、jvisualvm)的实战使用。通过真实案例,帮助学习者掌握 Java 应用在生产环境中的性能分析与优化能力。

19

2026.01.20

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.8万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 2.9万人学习

CSS教程
CSS教程

共754课时 | 21.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号