Generating a PDF in nodejs environment

Contraints:

  • as light weight as possible
  • should not need to worry about browser - client side ruled out
  • preferably use html (as html templates + are already being )
Options pitched:

https://www.npmjs.com/package/html-pdf
HTML to PDF converter that uses phantomjs

https://pdfcrowd.com/doc/api/html-to-pdf/nodejs/
The Pdfcrowd HTML to PDF API lets you convert web pages and HTML files to PDF in your Node.js applications.

https://www.npmjs.com/package/html2pdf.js/v/0.9.0
Client-side HTML-to-PDF rendering using pure JS

https://medium.com/@kainikhil/nodejs-how-to-generate-and-properly-serve-pdf-6835737d118e
NodeJS : How to generate and properly serve PDF

https://www.npmjs.com/package/pdfmake
Client/server side PDF printing in pure JavaScript


https://blog.risingstack.com/pdf-from-html-node-js-puppeteer/

First try:

PDFMake - ruled out
- could not set text color flexibly enough (only 7-8 preset colours available; which is weird)

some sample code in pdf make. (presented as it was before being discarded)
- first tried to render to file (but mac preview unlike linux okular / evince does not auto reload)
- so set-up a browser link to atleast have a cmd+r shortcut to refresh
- which resulted in the script below:

///////////////// write pdf to file /////////////////

// const fsPath = require('path');
// const envConf = require('../app-env');

// if (envConf.isDevelRun()) {
// require('dotenv').config({
// path: fsPath.resolve(__dirname, '../env/development.rc')
// });
// } else {
// require('dotenv').config({
// path: fsPath.resolve(__dirname, '../env/production.rc')
// });
// }

// const coreLib = require('../core');

// const logMaker = coreLib.utils.logMaker;
// const logger = logMaker.mkLogger();

// const fonts = {
//  Roboto: {
//      normal: 'test/fonts/Roboto-Regular.ttf',
//      bold: 'test/fonts/Roboto-Medium.ttf',
//      italics: 'test/fonts/Roboto-Italic.ttf',
//      bolditalics: 'test/fonts/Roboto-MediumItalic.ttf'
//  }
// };

// const PdfPrinter = require('pdfmake');
// // const printer = new PdfPrinter(fonts);
// const printer = new PdfPrinter(fonts);
// const fs = require('fs');

// const document

const stylesObj = {
header: {
fontSize: 22,
bold: true
}
};

const myLogo = {
image: 'assets/logo_2x_1274x224_72dpi.png',
width: 144
};

const docHeader = {
image: myLogo.image,
width: myLogo.width,
margin: [72, 72, 0, 0]
};

const docFooter = function(currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; };

const welcomePage = [
{text: "Example.com Preliminary Consultation Report", color:'blue', opacity: 0.5, style: ['header']},
{text: "", pageBreak: 'after'}
];

const docDefinition = {
info: {
title: 'Example.com Preliminary Consultation Report',
author: 'Team Example',
// subject: 'subject of document',
// keywords: 'keywords for document',
},
pageSize: "A4",
pageMargins: [72, 108, 72, 72], // 72pt => 1 inch
header: docHeader,
footer: docFooter,
    // content: [
    //  'First paragraph',
// 'Another paragraph, this time a little bit longer to make sure, this line will be divided into at least two lines',
// 'TEsting'
// ],
content: welcomePage,
styles: stylesObj
};

// var pdfDoc = printer.createPdfKitDocument(docDefinition);


// (async () => {
// try {
// pdfDoc.pipe(fs.createWriteStream('basics.pdf'));
// pdfDoc.end();

// // process.exit(0);

// } catch (err) {
// logger.info(err);
// process.exit(1);
// }
// })();


///////////////// serve a pdf doc server script /////////////////
var http = require('http');
var express = require('express');
var path = require('path');
var bodyParser = require('body-parser');

var pdfMakePrinter = require('pdfmake');

var app = express();

app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json({ limit: '50mb' }));
app.use(bodyParser.urlencoded({ extended: false }));

function createPdfBinary(pdfDoc, callback) {

var fontDescriptors = {
Roboto: {
normal: path.join(__dirname, '/fonts/Roboto-Regular.ttf'),
bold: path.join(__dirname, '/fonts/Roboto-Medium.ttf'),
italics: path.join(__dirname, '/fonts/Roboto-Italic.ttf'),
bolditalics: path.join(__dirname, '/fonts/Roboto-MediumItalic.ttf')
}
};

var printer = new pdfMakePrinter(fontDescriptors);

var doc = printer.createPdfKitDocument(pdfDoc);

var chunks = [];
var result;

doc.on('data', function (chunk) {
chunks.push(chunk);
});
doc.on('end', function () {
result = Buffer.concat(chunks);
callback(result);
});
doc.end();

}

app.get('/pdf', function (req, res) {
console.log("got a request !!");

createPdfBinary(docDefinition, function(binary) {
res.contentType('application/pdf');
res.send(binary);
}, function(error) {
res.send('ERROR:' + error);
});

});

var server = http.createServer(app);
var port = process.env.PORT || 8234;
server.listen(port);

console.log('http server listening on %d', port);

-x-x-x-

Next planning to try html-pdf

Works like a charm.

- Loading images is a bit of a challenge.
Need to use file system absolute path
(it seems phantomJS loads the html string as if a browser opens a local html file)
https://stackoverflow.com/a/53467747

- seems pretty light weight.

-x-x-x-
Yet to try this one:
https://www.pagedjs.org/documentation/

Comments

Popular Posts