Merge PDF with PDF-LIB

Tags: ,



I am trying to replicate the official example for merging 2 pdf files, but instead of hardcode the name of the file, I’d like to have the user upload two files. The code works well when the filename is hardcoded (see url2) but doesn’t work when trying to retrieve the filename from the input tag. What am I doing wrong?

async function copyPages() {
    // Fetch first existing PDF document
    const url1 = document.getElementById('file1').file[0].name
    //const url1 = 'Patient_Card.pdf'
    const doc1 = await fetch(url1).then(res => res.arrayBuffer())

    // Fetch second existing PDF document
    const url2 = 'Patient_Card.pdf'
    const doc2 = await fetch(url2).then(res => res.arrayBuffer())

    // Load a PDFDocument from each of the existing PDFs
    const pdf1 = await PDFDocument.load(doc1)
    const pdf2 = await PDFDocument.load(doc2)

    // Create a new PDFDocument
    const mergedPdf = await PDFDocument.create();

    const copiedPagesA = await mergedPdf.copyPages(pdf1, pdf1.getPageIndices());
    copiedPagesA.forEach((page) => mergedPdf.addPage(page));

    const copiedPagesB = await mergedPdf.copyPages(pdf2, pdf2.getPageIndices());
    copiedPagesB.forEach((page) => mergedPdf.addPage(page));

    const mergedPdfFile = await mergedPdf.save();

    // Trigger the browser to download the PDF document
    download(mergedPdfFile, "pdf-lib_page_copying_example.pdf", "application/pdf");
}

Answer

  1. I think the problem is in this code: I guess you would like to write: “files[0]” instead of “file[0]”.

  2. fetch method requires url (path) to resource from the web, but your uploaded file is not available under url1. You can try it by typing url1 in address bar in browser.

  3. I think that variable doc2 is not required. Probably you could write directly:

    const pdf2 = await PDFDocument.load('Patient_Card.pdf')

const url1 = document.getElementById('file1').file[0].name
const doc1 = await fetch(url1).then(res => res.arrayBuffer())

Working for me code:

<html>
<head>
   <script src="https://unpkg.com/pdf-lib/dist/pdf-lib.js"></script>
   <script>
      function readFileAsync(file) {
         return new Promise((resolve, reject) => {
            let reader = new FileReader(); 
            reader.onload = () => {
               resolve(reader.result);
            }; 
            reader.onerror = reject; 
            reader.readAsArrayBuffer(file);
         })
      }
      function download(file, filename, type) {
         const link = document.getElementById('link');
         link.download = filename;
         let binaryData = [];
         binaryData.push(file);
         link.href = URL.createObjectURL(new Blob(binaryData, {type: type}))
      }
      async function merge() {
         let PDFDocument = PDFLib.PDFDocument;

         const in1 = document.getElementById('file1').files[0];
         const in2 = document.getElementById('file2').files[0]; 
         let bytes1 = await readFileAsync(in1);
         let bytes2 = await readFileAsync(in2); 
         const pdf1 = await PDFDocument.load(bytes1);
         const pdf2 = await PDFDocument.load(bytes2);

         const mergedPdf = await PDFDocument.create(); 
         const copiedPagesA = await mergedPdf.copyPages(pdf1, pdf1.getPageIndices());
         copiedPagesA.forEach((page) => mergedPdf.addPage(page)); 
         const copiedPagesB = await mergedPdf.copyPages(pdf2, pdf2.getPageIndices());
         copiedPagesB.forEach((page) => mergedPdf.addPage(page)); 
         const mergedPdfFile = await mergedPdf.save();

         download(mergedPdfFile, 'pdf-lib_page_copying_example.pdf', 'application/pdf')
      }
   </script>
</head>
<body>
   <input type="file" id="file1"> <br>
   <input type="file" id="file2"> <br>
   <button onclick="merge()">Merge</button> <br>
   <a id="link">Download</a>
</body>
</html>


Source: stackoverflow