Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NodeJS: Merge two PDF files into one using the buffer obtained by reading them

Tags:

I am using fill-pdf npm module for filling template pdf's and it creates new file which is read from the disk and returned as buffer to callback. I have two files for which i do the same operation. I want to combine the two buffers there by to form a single pdf file which i can send back to the client. I tried different methods of buffer concatenation. The buffer can be concatenated using Buffer.concat, like,

var newBuffer = Buffer.concat([result_pdf.output, result_pdf_new.output]); 

The size of new buffer is also the sum of the size of the input buffers. But still when the newBuffer is sent to client as response, it shows only the file mentioned last in the array.

res.type("application/pdf"); return res.send(buffer); 

Any idea ?

like image 558
Abdul Vajid Avatar asked Apr 21 '16 10:04

Abdul Vajid


2 Answers

HummusJS supports combining PDFs using its appendPDFPagesFromPDF method

Example using streams to work with buffers:

const hummus = require('hummus'); const memoryStreams = require('memory-streams');  /**  * Concatenate two PDFs in Buffers  * @param {Buffer} firstBuffer   * @param {Buffer} secondBuffer   * @returns {Buffer} - a Buffer containing the concactenated PDFs  */ const combinePDFBuffers = (firstBuffer, secondBuffer) => {     var outStream = new memoryStreams.WritableStream();      try {         var firstPDFStream = new hummus.PDFRStreamForBuffer(firstBuffer);         var secondPDFStream = new hummus.PDFRStreamForBuffer(secondBuffer);          var pdfWriter = hummus.createWriterToModify(firstPDFStream, new hummus.PDFStreamForResponse(outStream));         pdfWriter.appendPDFPagesFromPDF(secondPDFStream);         pdfWriter.end();         var newBuffer = outStream.toBuffer();         outStream.end();          return newBuffer;     }     catch(e){         outStream.end();         throw new Error('Error during PDF combination: ' + e.message);     } };  combinePDFBuffers(PDFBuffer1, PDFBuffer2); 
like image 183
Zach Esposito Avatar answered Sep 28 '22 07:09

Zach Esposito


As mentioned by @MechaCode, the creator has ended support for HummusJS.

So I would like to give you 2 solutions.

  1. Using node-pdftk npm module

    The Following sample code uses node-pdftk npm module to combine two pdf buffers seamlessly.

    const pdftk = require('node-pdftk');  var pdfBuffer1 = fs.readFileSync("./pdf1.pdf"); var pdfBuffer2 = fs.readFileSync("./pdf2.pdf");  pdftk     .input([pdfBuffer1, pdfBuffer2])     .output()     .then(buf => {         let path = 'merged.pdf';         fs.open(path, 'w', function (err, fd) {             fs.write(fd, buf, 0, buf.length, null, function (err) {                 fs.close(fd, function () {                     console.log('wrote the file successfully');                 });             });         });     }); 

    The requirement for node-pdftk npm module is you need to install the PDFtk library. Some of you may find this overhead / tedious. So I have another solution using pdf-lib library.

  2. Using pdf-lib npm module

    const PDFDocument = require('pdf-lib').PDFDocument  var pdfBuffer1 = fs.readFileSync("./pdf1.pdf");  var pdfBuffer2 = fs.readFileSync("./pdf2.pdf");  var pdfsToMerge = [pdfBuffer1, pdfBuffer2]  const mergedPdf = await PDFDocument.create();  for (const pdfBytes of pdfsToMerge) {      const pdf = await PDFDocument.load(pdfBytes);      const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());     copiedPages.forEach((page) => {          mergedPdf.addPage(page);      });  }   const buf = await mergedPdf.save();        // Uint8Array  let path = 'merged.pdf';  fs.open(path, 'w', function (err, fd) {     fs.write(fd, buf, 0, buf.length, null, function (err) {         fs.close(fd, function () {             console.log('wrote the file successfully');         });      });  });   

Personally I prefer to use pdf-lib npm module.

like image 23
Pankaj Shinde Avatar answered Sep 28 '22 08:09

Pankaj Shinde