刘秀平 發表於 2020-4-15 08:55:00

使用 pdf-lib 在 Node.js 中处理 PDF

<p>pdf-lib npm 模块是使用Node.js创建和编辑PDF的好工具。 Puppeteer 是可以从HTML生成PDF的出色工具,但是不幸的是,以我的经验,浏览器对CSS中的打印布局的支持不是很好。 pdf-lib 模块为你提供了对PDF的非常精细的控制,它可以用来合并PDF,添加页码、水印,拆分PDF,以及你可能会使用 ILovePDF API 来进行的其它任何处理PDF文件的功能。</p>
<h3 id="入门">入门</h3>
<p>让我们使用 pdf-lib 创建一个简单的PDF文档。 这个PDF文档只有1页,页面中间会显示 Mastering JS 的图标。</p>
<pre><code>const { PDFDocument } = require('pdf-lib');
const fs = require('fs');

run().catch(err =&gt; console.log(err));

async function run() {
// Create a new document and add a new page
const doc = await PDFDocument.create();
const page = doc.addPage();

// Load the image and store it as a Node.js buffer in memory
let img = fs.readFileSync('./logo.png');
img = await doc.embedPng(img);

// Draw the image on the center of the page
const { width, height } = img.scale(1);
page.drawImage(img, {
    x: page.getWidth() / 2 - width / 2,
    y: page.getHeight() / 2 - height / 2
});

// Write the PDF to a file
fs.writeFileSync('./test.pdf', await doc.save());
}
</code></pre>
<p>运行上面的脚本会生成下面的PDF。 使用 pdf-lib 非常简单,只有一些陷阱:注意<code>PDFDocument#embedPng()</code>和<code>PDFDocument#save()</code>返回<code>Promise</code>,因此你需要使用<code>await</code>。</p>
<p><img src="https://img2020.cnblogs.com/blog/1072615/202004/1072615-20200415085349225-674594167.png"></p>
<h3 id="合并pdf">合并PDF</h3>
<p>pdf-lib 的杀手级功能是你可以修改已存在的PDF,而不仅仅是创建新的PDF。 例如,假设您有两个PDF:一个包含电子书的封面,另一个包含电子书的内容。 如何合并两个PDF呢? 我在上一本电子书(Mastering Async/Await)中使用了 ILovePDF API,但是 pdf-lib 使这个任务在 Node.js 中变得很容易。</p>
<p>有两个PDF文件:<code>cover.pdf</code>和<code>page-30-31.pdf</code>。 下面的脚本,使用 pdf-lib 将这两个PDF合并为了一个 <code>test.pdf</code> 文件。</p>
<pre><code>const { PDFDocument } = require('pdf-lib');
const fs = require('fs');

run().catch(err =&gt; console.log(err));

async function run() {
// Load cover and content pdfs
const cover = await PDFDocument.load(fs.readFileSync('./cover.pdf'));
const content = await PDFDocument.load(fs.readFileSync('./page-30-31.pdf'));

// Create a new document
const doc = await PDFDocument.create();

// Add the cover to the new doc
const = await doc.copyPages(cover, );
doc.addPage(coverPage);

// Add individual content pages
const contentPages = await doc.copyPages(content, content.getPageIndices());
for (const page of contentPages) {
    doc.addPage(page);
}

// Write the PDF to a file
fs.writeFileSync('./test.pdf', await doc.save());
}
</code></pre>
<p>合并后效果可见下图。</p>
<p><img src="https://img2020.cnblogs.com/blog/1072615/202004/1072615-20200415085412608-1635246717.png"></p>
<h3 id="添加页码">添加页码</h3>
<p>使用 Puppeteer 从HTML生成PDF的最大难点之一就是添加页码十分痛苦。 添加页码虽然看起来很简单,但是CSS打印布局却无法正确实现这个功能。 可以看一下我写的一个for循环用了 hard-code 像素偏移量才能使页码可以正确地显示。</p>
<p>例如,<em>Mastering Async / Await</em> 这个PDF的前4页没有页码:<code>./content.pdf</code>。 下面的脚本,将给PDF中的每一页添加页面。</p>
<pre><code>const { PDFDocument, StandardFonts, rgb } = require('pdf-lib');
const fs = require('fs');

run().catch(err =&gt; console.log(err));

async function run() {
const content = await PDFDocument.load(fs.readFileSync('./content.pdf'));

// Add a font to the doc
const helveticaFont = await content.embedFont(StandardFonts.Helvetica);

// Draw a number at the bottom of each page.
// Note that the bottom of the page is `y = 0`, not the top
const pages = await content.getPages();
for (const of Object.entries(pages)) {
    page.drawText(`${+i + 1}`, {
      x: page.getWidth() / 2,
      y: 10,
      size: 15,
      font: helveticaFont,
      color: rgb(0, 0, 0)
    });
}

// Write the PDF to a file
fs.writeFileSync('./test.pdf', await content.save());
}
</code></pre>
<p>添加页码后的效果可见下图<br>
<img src="https://img2020.cnblogs.com/blog/1072615/202004/1072615-20200415085438549-1685799902.png"></p>
<h3 id="继续">继续</h3>
<p>Node.js生态系统中有很多着出色的库,可以解决你几乎能想到的任何问题。 pdf-lib 模块可让你处理PDF,sharp 可让您处理几乎所有带有图像的东西,pkg 将Node项目捆绑到独立的可执行文件中,等等。 在你开始寻找线上 API 来解决你遇到的问题之前,如果先尝试搜索 npm,你可能会找到一个更好的解决方案。</p>
<blockquote>
<p>原文:Working With PDFs in Node.js Using pdf-lib</p>
</blockquote><br><br>
来源:https://www.cnblogs.com/tianliupingzong/p/12703007.html
頁: [1]
查看完整版本: 使用 pdf-lib 在 Node.js 中处理 PDF