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

pdf-lib npm 模块是使用Node.js创建和编辑PDF的好工具。 Puppeteer 是可以从HTML生成PDF的出色工具,但是不幸的是,以我的经验,浏览器对CSS中的打印布局的支持不是很好。 pdf-lib 模块为你提供了对PDF的非常精细的控制,它可以用来合并PDF,添加页码、水印,拆分PDF,以及你可能会使用 ILovePDF API 来进行的其它任何处理PDF文件的功能。

入门

让我们使用 pdf-lib 创建一个简单的PDF文档。 这个PDF文档只有1页,页面中间会显示 Mastering JS 的图标。

const { PDFDocument } = require('pdf-lib');
const fs = require('fs');

run().catch(err => 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());
}

运行上面的脚本会生成下面的PDF。 使用 pdf-lib 非常简单,只有一些陷阱:注意PDFDocument#embedPng()PDFDocument#save()返回Promise,因此你需要使用await

一个简单PDF

合并PDF

pdf-lib 的杀手级功能是你可以修改已存在的PDF,而不仅仅是创建新的PDF。 例如,假设您有两个PDF:一个包含电子书的封面,另一个包含电子书的内容。 如何合并两个PDF呢? 我在上一本电子书(Mastering Async/Await)中使用了 ILovePDF API,但是 pdf-lib 使这个任务在 Node.js 中变得很容易。

有两个PDF文件:cover.pdfpage-30-31.pdf。 下面的脚本,使用 pdf-lib 将这两个PDF合并为了一个 test.pdf 文件。

const { PDFDocument } = require('pdf-lib');
const fs = require('fs');

run().catch(err => 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 [coverPage] = await doc.copyPages(cover, [0]);
  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());
}

合并后效果可见下图。

合并PDF

添加页码

使用 Puppeteer 从HTML生成PDF的最大难点之一就是添加页码十分痛苦。 添加页码虽然看起来很简单,但是CSS打印布局却无法正确实现这个功能。 可以看一下我写的一个for循环用了 hard-code 像素偏移量才能使页码可以正确地显示。

例如,Mastering Async / Await 这个PDF的前4页没有页码:./content.pdf。 下面的脚本,将给PDF中的每一页添加页面。

const { PDFDocument, StandardFonts, rgb } = require('pdf-lib');
const fs = require('fs');

run().catch(err => 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 [i, page] 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());
}

添加页码后的效果可见下图
添加页码

继续

Node.js生态系统中有很多着出色的库,可以解决你几乎能想到的任何问题。 pdf-lib 模块可让你处理PDF,sharp 可让您处理几乎所有带有图像的东西,pkg 将Node项目捆绑到独立的可执行文件中,等等。 在你开始寻找线上 API 来解决你遇到的问题之前,如果先尝试搜索 npm,你可能会找到一个更好的解决方案。

原文:Working With PDFs in Node.js Using pdf-lib

猜你喜欢

转载自www.cnblogs.com/tianliupingzong/p/12703007.html
今日推荐