使用 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM