PDF documents are commonly used files in the majority of web applications. PDF documents are used in billing invoices, generating transaction reports, drafting the online agreement, etc. If you are building a SaaS then you might end up writing code or using a service to handle generating PDF documents on the fly as required by the system.
In this tutorial, we are going to learn how to generate PDF documents on the fly using Node.js and the Bull queue system.
Generating PDF Documents using Nodejs and Bull
Bull is a Redis-backed queue system built for scalability. To use Bull, you must have Redis key-value database running in your system. You can download and run Redis by following the guide from the official download page of Redis.
Let’s begin with the project.
Create new project in Node
To create a new project in Node, create a new folder and name it as you like, open the terminal or command prompt and switch to the folder you created using the cd command.
Run this command to create a new Node project.
This command will generate the boilerplate package.json for your project.
Run this command to install the dependencies required by the project.
Let’s code our project. Our codebase is divided into two important files, first is job.js which is responsible for creating jobs in the queue, and the second file is worker.js responsible for fulfilling the jobs and creating PDF files.
Let’s check out each file and codebase first. Here is the job.js code.
const invoice = require('./invoice');
const queue = new bull('pdf-generation');
function startJob() {
let invoiceData = invoice.content;
invoiceData.forEach(async (singleInvoice) => {
// push data in queue
let job = await queue.add({
title: `Generate invoice ${singleInvoice.index}`,
template: singleInvoice.text,
}, {'delay': 1000});
});
}
startJob();
In this file, we are going through all the records present in the invoice.js file. This is for sample record purposes, you can very well use the database records to the same.
Here is the sample content of invoice.js.
content: [{
'index': 1,
'text': 'Hello Shahid, You are charged $100 this month for services.'
},{
'index': 2,
'text': 'Hello Jack, You are charged $50 this month for services.'
},{
'index': 3,
'text': 'Hello Linda, You are charged $76 this month for services.'
}]
}
The codebase in job.js retrieve and loop over this records and creates jobs in the queue for each record by having a delay of 1000ms. Let’s check out our worker.js code.
const queue = new bull('pdf-generation');
const pdfKit = require('pdfkit');
const fs = require('fs');
function startProcess() {
// listen to the queue
// start processing email
queue.process((job) => {
// on each request generate the pdf
console.log(`Processing Job with id ${job.id}`);
generatePdfInvoice(job.data);
});
}
function generatePdfInvoice(data) {
let doc = new pdfKit;
doc.pipe(fs.createWriteStream(`${__dirname}/invoice/${data.title}.pdf`));
doc.fontSize(14).text(data.template, 100, 100);
doc.end();
console.log(`Generated PDF document`);
}
startProcess();
console.log('Worker running');
We are using a node module called pdfkit to generate our PDF documents. The function startProcess() invokes the worker job and it listens to the queue and wait for any messages.
Once it receives a message, we are calling generatePdfInvoice() function with the information received in the message. In the generatePdfInvoice() function, we are creating the PDF record by using the data coming from the queue and writing the PDF file in the invoice folder.
Let’s run the code and see it’s working.
First, run the job.js code using the following command.
Then, run the worker.js file.
Open the invoice folder and check the PDF files.
We have successfully created the PDF file. This is a sample PDF file and you can add as many details as you want including images, tables, etc in your PDF files.
Conclusion
We have studied how to use Node and queue systems such as Bull to design and build systems to generate PDF documents on the fly for business purposes.