0

0

将HTML表格导出为PDF:使用jsPDF与html2canvas的完整指南

花韻仙語

花韻仙語

发布时间:2025-07-12 15:04:11

|

744人浏览过

|

来源于php中文网

原创

将HTML表格导出为PDF:使用jsPDF与html2canvas的完整指南

本教程详细介绍了如何使用jsPDF和html2canvas库将网页中的HTML表格导出为PDF文件。文章涵盖了必要的库引用、核心JavaScript代码逻辑、完整的示例以及常见的错误排查方法,特别是针对“jsPDF未定义”这类因依赖缺失导致的错误,旨在帮助开发者顺利实现HTML内容到PDF的转换功能。

1. 引言:HTML表格导出PDF的需求与挑战

在web开发中,将动态生成的或静态的html内容(特别是表格数据)导出为可打印、可分享的pdf文件是一项常见需求。虽然浏览器提供了打印功能,但其样式和布局控制有限。为了实现更精细的pdf生成,我们通常会借助javascript库。jspdf是一个强大的客户端pdf生成库,能够创建各种pdf文档。然而,jspdf本身并不直接“理解”html元素的渲染样式,因此,当需要将复杂的html结构(如带有css样式的表格)转换为pdf时,我们通常需要结合一个能够将html渲染成图片的工具,例如html2canvas。html2canvas可以将dom元素渲染到html <canvas> 元素上,然后jspdf可以将这个canvas图像嵌入到pdf中。

2. 核心工具:jsPDF与html2canvas

要将HTML表格导出为PDF,我们需要两个关键的JavaScript库:

  • jsPDF: 用于生成PDF文档。它提供了添加文本、图像、形状等多种功能,并最终将内容保存为PDF文件。
  • html2canvas: 用于将HTML元素(如表格)渲染成Canvas图像。jsPDF无法直接将HTML结构转换为PDF,而是通过html2canvas将HTML渲染为图像,再将图像添加到PDF中。

3. 库的引入与准备

在使用这两个库之前,必须在HTML文件中正确引入它们。建议将脚本标签放置在 </body> 标签之前,或者使用 defer 属性,以确保DOM内容加载完成后再执行脚本。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HTML表格导出PDF示例</title>
    <style>
        table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 20px;
        }
        th, td {
            border: 1px solid #ccc;
            padding: 8px;
            text-align: left;
        }
        th {
            background-color: #f2f2f2;
        }
        button {
            padding: 10px 15px;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            margin-top: 20px;
        }
        button:hover {
            background-color: #0056b3;
        }
    </style>
</head>
<body>

    <h1>产品销售报告</h1>

    <table id="sales-table">
        <thead>
            <tr>
                <th>产品ID</th>
                <th>产品名称</th>
                <th>销售数量</th>
                <th>销售额</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>P001</td>
                <td>笔记本电脑</td>
                <td>150</td>
                <td>150000</td>
            </tr>
            <tr>
                <td>P002</td>
                <td>智能手机</td>
                <td>300</td>
                <td>210000</td>
            </tr>
            <tr>
                <td>P003</td>
                <td>无线耳机</td>
                <td>500</td>
                <td>75000</td>
            </tr>
            <tr>
                <td>P004</td>
                <td>显示器</td>
                <td>80</td>
                <td>64000</td>
            </tr>
        </tbody>
    </table>

    <button id="export-pdf-btn">导出为PDF</button>

    <!-- 引入 html2canvas 库 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
    <!-- 引入 jsPDF 库 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>

    <script src="app.js"></script> <!-- 您的自定义JavaScript文件 -->

</body>
</html>

重要提示: 请确保 html2canvas.min.js 和 jspdf.umd.min.js 这两个CDN链接是可访问且正确的。它们的顺序通常不严格,但为了避免潜在的依赖问题,通常先引入 html2canvas 再引入 jsPDF 是一个稳妥的做法,尽管对于独立的使用方式,顺序影响不大。

4. JavaScript 导出逻辑

以下是实现HTML表格导出为PDF的核心JavaScript代码 (app.js):

立即学习前端免费学习笔记(深入)”;

// 确保DOM内容加载完成后再执行脚本
document.addEventListener("DOMContentLoaded", () => {
    const exportPdfBtn = document.getElementById("export-pdf-btn");
    const table = document.getElementById("sales-table"); // 确保ID与HTML中的表格ID匹配

    exportPdfBtn.addEventListener("click", () => {
        // 使用html2canvas将HTML表格渲染为Canvas图像
        html2canvas(table, {
            scale: 2 // 提高渲染质量,可选
        }).then((canvas) => {
            // 获取Canvas图像的Data URL
            const imgData = canvas.toDataURL("image/png");

            // 创建一个新的jsPDF实例
            // 默认单位为pt (points), 页面大小为A4 (210mm x 297mm)
            // 可以通过 new jsPDF('p', 'mm', 'a4') 等方式自定义
            const doc = new window.jspdf.jsPDF(); // 注意:在UMD模块中,jsPDF可能挂载在window.jspdf下

            // 计算图像在PDF中的位置和尺寸
            // 假设PDF宽度为210mm (A4), 图像宽度180mm,留白15mm
            const imgWidth = 180; 
            const pageHeight = doc.internal.pageSize.height;
            const imgHeight = (canvas.height * imgWidth) / canvas.width;
            let position = 10; // 初始Y坐标

            // 如果图像高度超过一页,则分多页添加
            if (imgHeight > pageHeight - 20) { // 20是上下边距
                let heightLeft = imgHeight;
                let curPage = 1;

                while (heightLeft > 0) {
                    const pageCanvas = document.createElement('canvas');
                    const pageCtx = pageCanvas.getContext('2d');
                    pageCanvas.width = canvas.width;
                    pageCanvas.height = Math.min(canvas.height, (pageHeight - 20) * canvas.height / imgHeight); // 计算当前页的实际像素高度

                    // 从原始canvas中裁剪当前页内容
                    const sy = (curPage - 1) * ((pageHeight - 20) * canvas.height / imgHeight);
                    const sh = Math.min(canvas.height - sy, (pageHeight - 20) * canvas.height / imgHeight);

                    pageCtx.drawImage(canvas, 0, sy, canvas.width, sh, 0, 0, pageCanvas.width, pageCanvas.height);

                    const pageImgData = pageCanvas.toDataURL("image/png");

                    if (curPage > 1) {
                        doc.addPage();
                    }
                    doc.addImage(pageImgData, "PNG", 10, 10, imgWidth, (pageHeight - 20));
                    heightLeft -= (pageHeight - 20);
                    curPage++;
                }
            } else {
                // 如果图像在一页内,直接添加
                doc.addImage(imgData, "PNG", 10, position, imgWidth, imgHeight);
            }

            // 保存PDF文档
            doc.save("销售报告.pdf");
        }).catch(error => {
            console.error("生成PDF时发生错误:", error);
            alert("导出PDF失败,请检查控制台或稍后再试。");
        });
    });
});

代码解析:

  1. document.addEventListener("DOMContentLoaded", ...): 确保在DOM完全加载和解析后才执行JavaScript代码,避免找不到HTML元素的问题。
  2. html2canvas(table, { scale: 2 }): 调用 html2canvas 函数,传入要渲染的HTML元素(table)。scale: 2 参数可以提高生成图像的清晰度,但会增加处理时间和内存消耗。
  3. .then((canvas) => { ... }): html2canvas 返回一个Promise,当渲染完成后,会得到一个Canvas对象。
  4. canvas.toDataURL("image/png"): 将Canvas内容转换为PNG格式的Data URL,这是jsPDF可以识别的图像格式。
  5. const doc = new window.jspdf.jsPDF();: 创建jsPDF实例。注意,对于UMD(Universal Module Definition)模块,jsPDF 对象通常会挂载在 window.jspdf 下,而不是直接在全局作用域
  6. doc.addImage(imgData, "PNG", 10, position, imgWidth, imgHeight);: 将图像添加到PDF文档中。
    • imgData: 图像的Data URL。
    • "PNG": 图像格式。
    • 10, position: 图像在PDF页面上的X和Y坐标(单位默认为pt,或根据jsPDF实例的单位设置)。
    • imgWidth, imgHeight: 图像在PDF中的宽度和高度。
  7. 多页处理(可选但推荐): 上述代码包含了一个简单的多页处理逻辑,以防表格内容过长超出单页PDF高度。它会根据内容高度自动添加新页面并裁剪图像。
  8. doc.save("销售报告.pdf");: 保存生成的PDF文件,并指定文件名。

5. 常见问题与故障排除

在实现过程中,可能会遇到一些问题,以下是针对常见错误的排查方法:

Cardify卡片工坊
Cardify卡片工坊

使用Markdown一键生成精美的小红书知识卡片

下载

5.1 Uncaught ReferenceError: jsPDF is not defined 或 html2canvas is not defined

这是最常见的问题,也是原始问题中提到的错误。它意味着浏览器在尝试使用 jsPDF 或 html2canvas 对象时,它们尚未被加载或识别。

排查步骤:

  1. 检查CDN链接是否正确且可访问:
    • 确保你在HTML中引入的CDN链接(例如 https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js 和 https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js)没有拼写错误。
    • 尝试在浏览器中直接访问这些CDN链接,看是否能下载到对应的JavaScript文件。如果无法访问,可能是网络问题或CDN服务暂时不可用。
  2. 检查脚本加载顺序和位置:
    • 确保你的自定义JavaScript代码(app.js)是在 html2canvas 和 jsPDF 库之后加载的。
    • 将所有 <script> 标签放在 </body> 标签之前,或者使用 defer 属性,以确保DOM和库都已加载完毕再执行自定义脚本。
    • 特别注意: 对于 jsPDF 的UMD版本,它可能不会直接将 jsPDF 挂载到全局 window 对象下,而是挂载到 window.jspdf。因此,在代码中应使用 new window.jspdf.jsPDF() 来实例化,而不是 new jsPDF()。如果仍然报错,可以尝试 console.log(window.jspdf) 来确认其存在。
  3. 确认DOM加载完成:
    • 确保你的导出逻辑是在 DOMContentLoaded 事件监听器内部执行的,这样可以保证在尝试获取HTML元素(如按钮和表格)时,它们已经存在于DOM中。

5.2 导出的PDF为空白或内容不完整

  1. html2canvas 渲染问题:
    • 跨域资源: 如果你的HTML中包含来自不同域的图片或字体,html2canvas 可能会因为安全策略(CORS)而无法渲染它们。你需要确保这些资源设置了正确的CORS头,或者将它们托管在与你的页面相同的域下。
    • 复杂CSS/动画: html2canvas 并不完全支持所有CSS属性或JavaScript动画。对于非常复杂的布局或动态内容,它可能无法完美渲染。
    • 隐藏元素: 确保你要渲染的HTML元素(如表格)在页面上是可见的,并且没有 display: none; 或 visibility: hidden; 等CSS属性。
    • 渲染比例: 尝试调整 html2canvas 的 scale 参数,例如 scale: 2 或 scale: 3,以提高图像分辨率和清晰度。
  2. jsPDF addImage 参数问题:
    • 检查 doc.addImage() 的参数,特别是X、Y坐标和宽度、高度。如果这些值设置不当,图像可能会超出页面范围或尺寸过小。
    • 确认 imgData 是否确实包含了有效的图像数据(可以尝试在控制台打印 imgData 的前几百个字符,看它是否以 data:image/png;base64,... 开头)。

5.3 PDF样式与HTML不一致

html2canvas 是将HTML渲染为位图图像,而不是矢量图形。这意味着:

  • 文本清晰度: 文本在放大后可能会出现模糊,因为它被转换为图像的一部分。
  • 交互性缺失: PDF中的内容是图像,无法像HTML那样进行文本选择、链接点击等操作。
  • 字体问题: html2canvas 依赖于浏览器渲染字体。如果PDF中需要嵌入特定字体以保持一致性,jsPDF提供了字体嵌入功能,但这超出了 html2canvas 的范畴。

对于需要矢量文本和更高保真度的HTML到PDF转换,可能需要考虑更复杂的服务器端渲染方案(如使用Puppeteer结合PDF库),或者使用jsPDF的 html() 方法(该方法在内部也依赖 html2canvas 或类似机制,但可能提供更优化的处理)。

6. 总结

通过结合使用jsPDF和html2canvas,我们可以有效地将HTML表格或其他DOM元素导出为PDF文件。关键在于正确引入两个库,并理解它们各自在转换过程中的作用。html2canvas 负责将HTML渲染成图像,而jsPDF则负责将这些图像嵌入到PDF文档中。在开发过程中,遇到“未定义”错误时,首先应检查库的引入路径、加载顺序以及DOM是否已完全加载。掌握这些基本原则和故障排除技巧,将有助于您顺利实现Web页面的PDF导出功能。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
ajax教程
ajax教程

php中文网为大家带来ajax教程合集,Ajax是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,Ajax可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。php中文网还为大家带来ajax的相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

166

2023.06.14

ajax中文乱码解决方法
ajax中文乱码解决方法

ajax中文乱码解决方法有设置请求头部的字符编码、在服务器端设置响应头部的字符编码和使用encodeURIComponent对中文进行编码。本专题为大家提供ajax中文乱码相关的文章、下载、课程内容,供大家免费下载体验。

170

2023.08.31

ajax传递中文乱码怎么办
ajax传递中文乱码怎么办

ajax传递中文乱码的解决办法:1、设置统一的编码方式;2、服务器端编码;3、客户端解码;4、设置HTTP响应头;5、使用JSON格式。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

124

2023.11.15

ajax网站有哪些
ajax网站有哪些

使用ajax的网站有谷歌、维基百科、脸书、纽约时报、亚马逊、stackoverflow、twitter、hacker news、shopify和basecamp等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

260

2024.09.24

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

564

2023.09.20

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

531

2023.06.20

js获取当前时间
js获取当前时间

JS全称JavaScript,是一种具有函数优先的轻量级,解释型或即时编译型的编程语言;它是一种属于网络的高级脚本语言,主要用于Web,常用来为网页添加各式各样的动态功能。js怎么获取当前时间呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

576

2023.07.28

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

761

2023.08.03

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

49

2026.03.13

热门下载

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

精品课程

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

共14课时 | 0.9万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.6万人学习

CSS教程
CSS教程

共754课时 | 43.2万人学习

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

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