继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

用JavaScript把HTML转换成PDF的实例与代码讲解

慕斯709654
关注TA
已关注
手记 322
粉丝 38
获赞 183

在这篇博客里,我们将学习如何利用JavaScript将HTML页面转换成PDF。

在一个项目中,我需要用JavaScript进行一些HTML到PDF的转换。

这个网站很基础。页面中有一个包含表单的div元素,我只需要从这个div生成PDF文件,并将其在新标签页中显示出来。所有操作都在客户端完成,不需要后端服务器的支持。

这里的主要任务有:

  1. 将 PDF 转换为 HTML。
  2. 在新标签页中打开 PDF。
用 JavaScript 实现 HTML 到 PDF 的转换

所以呢,这里的第一条。就是把HTML转PDF,很简单,

一搜就找到了一个叫html2pdf的库。

根据其文档的描述,“html2pdf.js 通过利用 html2canvasjsPDF,完全在客户端上将该网页或元素转换为可打印的 PDF 文件。”

那正是我想要的。还有网上也有很多其他的相关教程。

一切都成功了,下载的pdf却是空的。

html2pdf 会生成并返回一个空白的 PDF

那有点怪。一查之下,这版有点不对劲。

用了0.9.3,问题就解决了。

CDN链接: https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.9.3/html2pdf.bundle.min.js

它显示了包含所有内容的 div(区块标签)。

JS 代码:

    let 元素 = document.getElementById('div-to-print')

    html2pdf().from(元素).save();

切换到全屏 退出全屏

它要么保存要么下载了 PDF 文件。

但我不需要它下载,我需要它在新标签页里打开。

使用 JavaScript 和 Blob 在新标签页中打开 PDF

我们需要从pdf文件创建一个新blob,并创建一个新的URL来显示该文件。通过阅读这个问题问题,我知道了可以通过使用html2pdf提供的Promise API来获取文件而不是直接下载它,然后用它来创建一个新的blob。

我们用一个普通的文件会怎么做这件事。

const 文件输入 = document.querySelector('input[type=file]').files[0];
let 文件blob = new Blob([文件输入], { type: 'application/pdf' });
let 文件url = URL.createObjectURL(文件blob);
window.open(文件url);

全屏模式,退出全屏

与通过 html2pdf 生成的 PDF 配合使用

    async function printHTML() {
        // 将HTML元素转换为PDF并打开下载窗口
        let worker = await html2pdf().from(element).toPdf().output('blob').then((data) => {
            // 打印数据到控制台
            console.log(data);
            // 创建一个URL对象用于下载文件
            let fileURL = URL.createObjectURL(data);
            // 打开一个新的窗口以显示下载的PDF文件
            window.open(fileURL);
        });
    }

切换到全屏模式,退出全屏

成功了。PDF不再下载,而是直接在新标签页中打开了。接着,我用CSS对div进行了样式设计。但是遇到了一个问题。

html2pdf CSS 效果未显示?

我编写的 div 的 CSS 在生成 PDF 时无法加载。使用 html2pdf 时,CSS 没有生效。

我查了一下,发现外部CSS并没有被html2css加载进来。结果只打印了HTML,CSS没打印出来。

解决方法是在HTML中使用style标签写CSS,或者直接使用内联CSS。在这个讨论中也提供了一些额外的解决办法。

最后,PDF终于生成了,符合我的需求。还有一个需要注意的地方。

html2pdf 转换后的文本不可选择

PDF里的文字不能选中。这可能对大多数项目来说不是必需的,但我需要这个。

html2pdf 生成 PDF 是通过 canvas 图,它一直都使用的是 html2canvas 这个工具,因此,PDF 中并没有文本,只是将 HTML 中的 canvas 图转换为 PDF。

我得换个库了。为什么不一直用我一直在用的那个库呢?

html2pdf 使用了 jsPDF。所以我尝试了 jsPDF

    doc.fromHTML(document.getElementById("div-to-print"),
         22, // Margins
         17,
         {'width': 400},
         function (a) {
              // doc.save("HTML2PDF.pdf"); // 保存文件
              Blob PDF = new Blob([doc.output()], { type: 'application/pdf' });
              let blobUrl = URL.createObjectURL(blobPDF);
              window.open(blobUrl); // 打开PDF文件
    });

Correction: "let blobPDF = new Blob([doc.output()], { type: 'application/pdf' });" should remain as the original "let blobPDF = new Blob([doc.output()], { type: 'application/pdf' });" since "let" is a necessary keyword in JavaScript, and the variable name "blobPDF" should not be changed. The corrected version is:

    doc.fromHTML(document.getElementById("div-to-print"),
         22, // Margins
         17,
         {'width': 400},
         function (a) {
              // doc.save("HTML2PDF.pdf"); // 保存文件
              let blobPDF = new Blob([doc.output()], { type: 'application/pdf' });
              let blobUrl = URL.createObjectURL(blobPDF);
              window.open(blobUrl); // 打开PDF文件
    });

进入全屏,退出全屏

这里一切都好

在 jsPDF 插件中,用新标签打开 PDF 文件而不是下载文件

至于在新标签页中直接打开而不是从jsPDF下载PDF文件,类似于html2pdf的情况,在回调函数中,我们可以传递doc.output()来创建blob对象。

生成的PDF是文本,而不是图像。

所以,一切顺利,我添加了CSS。但呢?

jsPDF 遇到问题,无法工作

原来jsPDF和CSS不兼容。要想让它们一起用,得用html2canvas才行。而这正是html2pdf一直在做的事。

我们可以很容易地在jsPDf中设置边距。它也支持像以前一样的html属性,例如“这是p one”。但我需要使用CSS的原因是因为我尝试打印的div内部有两个子div。其中一个需要在垂直和水平方向上都居中。

接下来我搜索的是“如何只用HTML居中div里的子元素,也不用CSS?”

结果发现jsPDF里有一个文本API,它可以接受多个参数值,这使得在没有CSS的情况下轻松完成工作。

API.text = function(文本, x, y, 标志, 角度, 对齐方式); // 设置文本的显示参数

进入全屏模式 退出全屏模式

只要再多几个这样的文本,这份工作就算完成了。

结果发现它确实有效,这真是太棒了。但是不用写多个文本内容,如果我能用withHTML函数做到这一点。

通过在添加前一个块的回调函数中再添加一个 HTML 元素块,就可以实现了。

再计算几次,用计算出的值作边距,就可以完美居中了。

// 该代码段用于从HTML元素生成PDF并打开
let pageHeight = doc.internal.pageSize.height || doc.internal.pageSize.getHeight();
// 获取文档页面的高度,如果height属性不存在则尝试获取实际高度
let pageWidth = doc.internal.pageSize.width || doc.internal.pageSize.getWidth();
// 获取文档页面的宽度,如果width属性不存在则尝试获取实际宽度
let recipientBlock = document.querySelector(".div2-block");
// 选择具有类名为“div2-block”的HTML元素
let rHeight = recipientBlock.clientHeight;
// 获取recipientBlock元素的实际高度
let rWidth = recipientBlock.clientWidth;
// 获取recipientBlock元素的实际宽度

doc.fromHTML(document.querySelector(".div1-block"),
    22, 17, { 'width': 200, 'height': 200 },
    function (a) {
        // 将具有类名为“div1-block”的HTML元素的内容转换为PDF并放置在指定位置
        doc.fromHTML(document.querySelector(".div2-block"),
            pageWidth / 2 - rWidth / 4,
            pageHeight / 2 - rHeight / 4,
            { 'width': 200, 'height': 200 },
            function (a) {
                // 将具有类名为“div2-block”的HTML元素的内容转换为PDF并放置在指定位置
                let blobPDF = new Blob([doc.output()], { type: 'application/pdf' });
                // 创建一个新的Blob对象,包含转换后的PDF数据,并指明类型为application/pdf
                let blobUrl = URL.createObjectURL(blobPDF);
                // 从Blob对象创建一个新的URL
                window.open(blobUrl);
                // 使用新创建的URL打开一个新的窗口来查看PDF
            });
    });

全屏模式,退出

最后,当项目快要结束时。

最后一步是要设置最终PDF的尺寸。

在那里文档中提到,而且非常简单。

将高度和宽度以数组形式传递并指定单位。由于某些原因,“px”(像素)单位在使用时出现了问题,因此改用了“pt”单位。这样就解决了问题。

let doc = new jsPDF({orientation: 'l', unit: 'pt', format: [widthForJsPDF, heightForJsPDF]})

进入全屏,退出全屏。

这就是用JavaScript将HTML转成PDF的方法,利用JavaScript将HTML转换成PDF,这就是完成一个项目的过程。

我只是做了些谷歌搜寻。

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP