zoukankan      html  css  js  c++  java
  • 使用 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

  • 相关阅读:
    Linux之Shell基本命令
    Linux之find命令
    C++11 auto类型说明符
    C++之类型转换
    C++中指针和引用的区别
    C++之引用
    [BUUCTF]PWN——[ZJCTF 2019]EasyHeap
    [BUUCTF]REVERSE——[WUSTCTF2020]level3
    [BUUCTF]REVERSE——[MRCTF2020]hello_world_go
    [BUUCTF]REVERSE——[GKCTF2020]BabyDriver
  • 原文地址:https://www.cnblogs.com/tianliupingzong/p/12703007.html
Copyright © 2011-2022 走看看