javascriptnode.jspuppeteerpdfmerger

Adding Header to Each Page of PDF in Node Puppeteer


I am trying to print a header section to each page of a PDF that gets generated. I'm also using pdf-merger to merge together multiple PDFs. Right now when I execute this code the PDF generated contains multiple documents, as expected. However the Header section I'm adding only seems to show up in the 2nd and 5th of the documents that are part of the full PDF. I cannot tell from looking at my code why that is happening. I would assume the Header would be added to each of the documents.

First question: why am I noticing the behavior I am. Understand that would help me know what to adjust. Second question: How can I adjust this code so that the Header is added to each of the pages of the document?

Here is the section where I pass options to page.pdf():

let doc = await page.pdf({
  displayHeaderFooter: true,
  format: "A4",
  printBackground: true,
  headerTemplate: '<span style="font-size: 30px; width: 50px; height: 50px; color:black; margin: 20px;">Header</span>', 
});

And here is the full block of code:

let merger = new PDFMerger();

    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    let recordNum = 1;
    for (let r of recordsArr) {
      try {
        let signatures = [];
        signatures = await signatureService.getSignatures({}, [r.guid]);
        if (signatures.length) r.signatureBase64Str = signatures[0].value;
      } catch (err) {
        console.log(err);
        return Response.Failure("Error occurred while obtaining signature.", err);
      }
      r.logoBase64Str = base64Logo;
      if (r.goalNotes.length) {
        for (const [i, value] of r.goalNotes.entries()) {
          value.number = i + 1;
        }
      }
      try {
        console.log(`processing record ${recordNum} of ${recordsArr.length}`);
        const content = await compile(r);
        await page.setContent(content);
        await page.emulateMediaType("screen");
        let doc = await page.pdf({
          displayHeaderFooter: true,
          format: "A4",
          printBackground: true,
          headerTemplate: '<span style="font-size: 30px; width: 50px; height: 50px; color:black; margin: 20px;">Header</span>', 
        });
        merger.add(doc);
        ++recordNum;
      } catch (error) {
        console.log(error);
        return Response.Failure("Unable to generate PDF by parameters passed.");
      }
    }

Solution

  • It's hard to tell what's wrong with your code since so many functions are undefined, but here's a minimal, runnable example that adds headers to all pages using the same PDF merger package as you:

    const PDFMerger = require("pdf-merger-js"); // ^4.3.0
    const puppeteer = require("puppeteer"); // ^21.4.1
    
    const headerTemplate = `<span style="font-size: 30px; width: 200px; height: 200px; background-color: black; color: white; margin: 20px;">Header</span>`;
    const mockContent = Array(10).fill().map((_, i) => `<div>page ${i}</div>`);
    const filename = "merged.pdf";
    const pdfSettings = {
      displayHeaderFooter: true,
      format: "A4",
      printBackground: true,
      headerTemplate, 
      margin: {top: "100px", bottom: "100px"},
    };
    
    let browser;
    (async () => {
      browser = await puppeteer.launch();
      const [page] = await browser.pages();
      const merger = new PDFMerger();
    
      for (const content of mockContent) {
        await page.setContent(content);
        merger.add(await page.pdf(pdfSettings));
      }
    
      await merger.save(filename);
    })()
      .catch(err => console.error(err))
      .finally(() => browser?.close());