Puppeteer 生成来自多个 HTML 字符串的 PDF

12

我正在使用Puppeteer从HTML字符串生成PDF文件。阅读文档后,我发现有两种生成PDF文件的方法:

第一种是通过传递一个URL地址并调用goto方法来实现:

page.goto('https://example.com');
page.pdf({format: 'A4'});

第二种情况是我的情况,需要调用方法setContent如下:

page.setContent('<p>Hello, world!</p>');
page.pdf({format: 'A4'});

我的问题是我收到了三个不同的HTML字符串,我想通过Puppeteer将它们合并成一个包含3页的PDF文件(假设我有3个HTML字符串)。

我想知道是否可以使用Puppeteer实现这个目标?如果可以的话,请提供其他建议,但我需要使用chrome-headless。


我基本上会这样处理: 1)使用puppeteer脚本进行三个单独的page.goto操作 2)一个变量来保存从这3个HTML页面中抓取的3个HTML字符串 3)最后生成3个单独的PDF文件我不确定您是否可以使用puppeteer合并PDF文档。如果您找到了解决方法,请在此处发布您的解决方案。 - tamak
3个回答

9
我是通过以下方法完成的:
  1. 使用puppeteer生成3个不同的PDF文件。您可以选择将文件保存在本地或存储到变量中。

  2. 我将文件保存在本地,因为我找到的所有PDF合并插件都只接受URL,不接受缓冲区。在同步生成本地PDF之后,我使用PDF Easy Merge将它们合并。

代码如下:

const page1 = '<h1>HTML from page1</h1>';
const page2 = '<h1>HTML from page2</h1>';
const page3 = '<h1>HTML from page3</h1>';

const browser = await puppeteer.launch();
const tab = await browser.newPage();
await tab.setContent(page1);
await tab.pdf({ path: './page1.pdf' });

await tab.setContent(page2); 
await tab.pdf({ path: './page2.pdf' });

await tab.setContent(page3);
await tab.pdf({ path: './page3.pdf' });

await browser.close();

pdfMerge([
  './page1.pdf',
  './page2.pdf',
  './page3.pdf',
],
path.join(__dirname, `./mergedFile.pdf`), async (err) => {
  if (err) return console.log(err);
  console.log('Successfully merged!');
})

page1、page2和page3是三个不同的URL还是browser.newPage()?同时,根据最新文档,将方法名称从setContent更改为content。 - Haresh Chhelana
页面1、页面2和页面3包含了三个不同页面的HTML代码,它们是字符串。感谢您提供content的提示。我会进行更新。 - Juan Rivillas
有没有任何开源的PDF合并库?因此,我可以看到easy-pdf merge不是开源的。 - Dharmarajan

6
我能够从下面的代码中生成多个PDF,这是关于多个URL的:

package.json

{
 ............
 ............

 "dependencies": {
    "puppeteer": "^1.1.1",
    "easy-pdf-merge": "0.1.3"
 }

 ..............
 ..............
}

index.js

const puppeteer = require('puppeteer');
const merge = require('easy-pdf-merge');

var pdfUrls = ["http://www.google.com","http://www.yahoo.com"];

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  var pdfFiles=[];

  for(var i=0; i<pdfUrls.length; i++){
    await page.goto(pdfUrls[i], {waitUntil: 'networkidle2'});
    var pdfFileName =  'sample'+(i+1)+'.pdf';
    pdfFiles.push(pdfFileName);
    await page.pdf({path: pdfFileName, format: 'A4'});
  }

  await browser.close();

  await mergeMultiplePDF(pdfFiles);
})();

const mergeMultiplePDF = (pdfFiles) => {
    return new Promise((resolve, reject) => {
        merge(pdfFiles,'samplefinal.pdf',function(err){

            if(err){
                console.log(err);
                reject(err)
            }

            console.log('Success');
            resolve()
        });
    });
};

运行命令:node index.js

有没有任何开源的PDF合并库?因此,我可以看到easy-pdf merge不是开源的。 - Dharmarajan
需要Java :( - AceP

6

pdf-merger-js是另一个选择。对于下面的page.gotopage.setContent应该可以完全替代:

const PDFMerger = require("pdf-merger-js"); // ^4.2.1
const puppeteer = require("puppeteer"); // ^19.7.2

const urls = [
  "https://news.ycombinator.com",
  "https://www.example.com",
  "https://en.wikipedia.org",
  // ...
];
const filename = "merged.pdf";

let browser;
(async () => {
  browser = await puppeteer.launch();
  const [page] = await browser.pages();
  const merger = new PDFMerger();

  for (const url of urls) {
    await page.goto(url);
    await merger.add(await page.pdf());
  }

  await merger.save(filename);
})()
  .catch(err => console.error(err))
  .finally(() => browser?.close());

这个插件对我也起作用了。我认为这是唯一一个仍在维护的插件。 - Ruben
2
这里还有一个.saveAsBuffer()选项,可以将PDF作为流返回,而不是保存到硬盘上。 - Itinerati

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接