Click Below to subscribe

How to Generate PDF in Node.js 2023

In this article, we gonna learn how to generate pdf in node.js. 

1. Let's create a new express project using express generator.

npm i -g express-generator
express node-pdf --view=hbs
cd node-pdf

2. Install puppeteer-html-pdf npm package.

npm i puppeteer-html-pdf

3. Create a folder controllers and inside this folder create pdf.controller.js

controllers/pdf.controller.js

const hbs = require('hbs');
const PuppeteerHTMLPDF = require('puppeteer-html-pdf');

exports.print = async (req, res) => {
    const pdfData = {
        invoiceItems: [
            { item: 'Website Design', amount: 5000 },
            { item: 'Hosting (3 months)', amount: 2000 },
            { item: 'Domain (1 year)', amount: 1000 },
        ],
        invoiceData: {
            invoice_id: 123,
            transaction_id: 1234567,
            payment_method: 'Paypal',
            creation_date: '04-05-1993',
            total_amount: 141.5,
        },
        baseUrl: `${req.protocol}://${req.get('host')}` // http://localhost:3000
    }

    const htmlPDF = new PuppeteerHTMLPDF();
    htmlPDF.setOptions({ format: 'A4' }); 

    try {
        const html = await htmlPDF.readFile('views/invoice.hbs', 'utf8');  
        const template = hbs.compile(html);
        const content = template(pdfData);

        const pdfBuffer = await htmlPDF.create(content); 
        res.attachment('invoice.pdf')
        res.end(pdfBuffer);
    } catch (error) {
        console.log(error);
        res.send('Something went wrong.')
    }
}

Ref:- https://www.npmjs.com/package/puppeteer-html-pdf

Note:- If want to store your exported file on the server you can use path option.

const options = {
	format: 'A4',
	path: 'storage/invoice.pdf' 
}

4. Create routes.

routes/index.js

const express = require('express');
const router = express.Router();
const pdfController = require('../controllers/pdf.controller');

router.get('/', pdfController.print); 

module.exports = router;

5. Create a file views/invoice.hbs and add the following code.

<html>

<head>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Invoice Example</title>
    <link rel="stylesheet" href="{{baseUrl}}/stylesheets/style.css" />
</head>

<body>
    <div class="invoice-box">
        <table cellpadding="0" cellspacing="0">
            <tr class="top">
                <td colspan="2">
                    <table>
                        <tr>
                            <td class="title">
                                <img src="{{baseUrl}}/images/logo.png" style="width: 100%; max-width: 88px" />
                            </td>
                            <td>
                                Invoice #:
                                {{invoiceData.invoice_id}}<br />
                                Created:
                                {{invoiceData.creation_date}}
                            </td>
                        </tr>
                    </table>
                </td>
            </tr>
            <tr class="information">
                <td colspan="2">
                    <table>
                        <tr>
                            <td>
                                Godaddy, LLC.<br />
                                12345 Sunny Road<br />
                                Sunnyville, CA 12345
                            </td>
                            <td>
                                Godaddy LLC.<br />
                                John Wick<br />
                                john@example.com
                            </td>
                        </tr>
                    </table>
                </td>
            </tr>
            <tr class="heading">
                <td>Payment Method</td>
                <td># Transaction Id</td>
            </tr>
            <tr class="details">
                <td>{{invoiceData.payment_method}}</td>
                <td>{{invoiceData.transaction_id}}</td>
            </tr>
            <tr class="heading">
                <td>Item</td>
                <td>Amount</td>
            </tr>
            {{#each invoiceItems}}
            <tr class="item {{#if @last}} last {{/if}}">
                <td>{{this.item}}</td>
                <td>{{this.amount}}</td>
            </tr>
            {{/each}}
            <tr class="total">
                <td></td>
                <td>Total: {{invoiceData.total_amount}}</td>
            </tr>
        </table>
    </div>
</body>

</html>

Note:- please checkout github repo - https://github.com/ultimateakash/node-pdf

6. Finally start the project.

npm start

Open http://localhost:3000 in the browser.

Leave Your Comment