NodeJS + Express + PDFKit + node-qrcode: Not able to add QR code to PDF - node.js

I am trying to implement a QR code in a PDF document using PDFkit (https://github.com/foliojs/pdfkit) and node-qrcode (https://github.com/soldair/node-qrcode).
Implementing PDF document:
const doc = new PDFDocument({
margin: 0,
size: 'LETTER'
})
doc.pipe(fs.createWriteStream('/files/result.pdf'))
doc.pipe(res)
Creating QR code and adding it to the PDF:
var opts = {
errorCorrectionLevel: 'H',
type: 'image/png',
quality: 0.9,
margin: 1,
color: {
dark:"#000000",
light:"#FFFFFF"
}
}
QRCode.toDataURL('http://link.to.website', function (err, url) {
if (err) throw err
doc.image(url, 50, 45, { width: 50 })
console.log(url)
})
Close the PDF:
doc.end()
Console output of the url from QRCode is correctly formatted and no error messages from PDFKit:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIQAAACECAYAAABRRIOnAAAAAklEQVR4AewaftIAAAOQSURBVO3BQY5jBxYDweSD7n/lHC+84OoDglTltocR8S/M/O2YKcdMOWbKMVOOmXLMlGOmHDPlmCnHTDlmyjFTjplyzJRjprz4UBJ+k8qTJHxC5R1JaCotCb9J5RPHTDlmyjFTXnyZyjcl4ZtUWhJaEppKS8InVL4pCd90zJRjphwz5cUPS8I7VN6RhG9S+U1JeIfKTzpmyjFTjpny4j9G5R0qLQnvUPkvOWbKMVOOmfLiPy4JTaUloam0JDSVloSm8m92zJRjphwz5cUPU/mTqbQkNJWWhG9S+ZMcM+WYKcdMefFlSfg3SUJTaUloKi0J70jCn+yYKcdMOWbKiw+p/EmS8CdR+Tc5ZsoxU46ZEv/CB5LQVFoSvknlSRKayjuS8AmVloRvUvlJx0w5ZsoxU158SKUloak8ScITlSdJaCotCU3lHSpPkvBEpSWhqbwjCU3lm46ZcsyUY6a8+GFJaCpPVFoSmsqTJLwjCU3lSRKaSktCU3lHEprKkyQ0lU8cM+WYKcdMefGhJDxRaUloKi0JTaUl4R0qLQnvSEJTaUloKk9UWhKayhOVloRvOmbKMVOOmfLihyWhqTxRaUloKt+k0pLwDpWWhCcq70jCbzpmyjFTjpny4h+WhCcqT5LwRKWptCQ0lZaEd6g8SUJTaUloKi0JTeWbjplyzJRjprz4MpWWhCcqT5LwiSQ0labyjiQ8UXmi8k1JaCqfOGbKMVOOmfLih6k8ScITlZaEpvIkCU+S0FSaypMktCQ0lZaET6i0JHzTMVOOmXLMlBf/MJWWhJaEptKS8E1JeKLyjiS8Q6Uloak0lW86ZsoxU46Z8uJDKt+k8ptU3pGEJyrvSEJLwj/pmCnHTDlmyosPJeE3qTSVloQnSXii0pLQVFoSniShqXwiCU9UPnHMlGOmHDPlxZepfFMSniThiUpLQlP5SSqfUPlNx0w5ZsoxU178sCS8Q+UTKt+k0pLwJAnflIR3qHzimCnHTDlmyov/MyotCU9Unqg8SUJTaUloKi0Jv+mYKcdMOWbKi/+YJDSVJyotCS0JTeUdKi0JTeUdKi0J33TMlGOmHDPlxQ9T+UkqT5LQVFoSnqg8ScITlSdJeKLym46ZcsyUY6a8+LIk/KYkNJVPqLQkNJWm8pOS8JuOmXLMlGOmxL8w87djphwz5Zgpx0w5ZsoxU46ZcsyUY6YcM+WYKcdMOWbKMVOOmfI/dLqWFdMR+T4AAAAASUVORK5CYII=
The problem is that no image is displayed in the produced PDF.
If I use any other functions (than doc.image), e.g. doc.text(), doc.circle() all elements works fine and added to the PDF.
Any idea how to solve this?

toDataURL() is a asynchronous method.
I didn't wait for it to complete.
Closed the PDF document after it completed, and that worked.

Related

Node.js How to add wkhtmltopdf result to PDFKit page?

Is there a way to concat the result of an an html page converted with wkhtmltopdf-node inside a document page created with pdfkit in node.js, instead of just creating a pdf file from html?
const doc = new PDFDocument({
bufferPages:true,
toc: true,
margins: {
top: 125,
bottom: 50,
left: 50,
right: 50
}
});
doc.pipe(fs.createWriteStream('output.pdf'));
doc.addPage();
doc.text("HTML Content ")
// concat the result of this conversion inside doc instead of out.pdf
wkhtmltopdf(params.content, { pageSize: 'letter' }).pipe(fs.createWriteStream('out.pdf'));
Something like
doc.concat(wkhtmltopdf(params.content, { pageSize: 'letter' }));

How to generate A4 size paginated pdf in phantomjs

I am generating pdf in nodejs using phantomjs. However, when I try to generate a large pdf (more than 1 A4 size page), it generates only two page pdf. One of the page contains all the matter and the other similar sized (very large) page is blank.
I am using the following code to generate the pdf:
phantom.create("--web-security=no", "--ignore-ssl-errors=yes",function(ph) {
return ph.createPage(function(page) {
return page.open(htmlfilepath, function(status) {
page.paperSize = { format: 'A4', orientation: 'portrait', border: '1cm' };
page.render(pdffilepath, function(){
ph.exit();
});
});
});
});
Can anyone tell the correct method to format pdf in phantomjs. Thanks.
Got it. Even though I did exactly according to many articles and tutorial online, I had to use change the following piece to code:
page.paperSize = { format: 'A4', orientation: 'portrait', border: '1cm' };
to this:
page.set('paperSize', { format: 'A4', orientation: 'portrait', border: '1cm'});
This may be because of the change in version from 1.x.x to 2.x.x.

Using blob in expressjs

I have a project in which i have to provide the user with a pdf generated using pdfkit and allowing users to download the same using blob. I am getting an error on doing so. Any help would be appreciated.
error-
TypeError: Blob is not a function
at BlobStream.toBlob (C:\Users\ws\node_modules\blob-stream\index.js:33:18)
Code Snippet:
var doc = new report();
var blobStream = require('blob-stream');
var stream = doc.pipe(blobStream());
doc.text('And here is some wrapped text...', 100, 300)
.font('Times-Roman', 13)
.moveDown()
.text('lorem', {
width: 412,
align: 'justify',
indent: 30,
columns: 2,
height: 300,
ellipsis: true
});
doc.end();
stream.on('finish',function(){
blob = stream.toBlob('Blob/pdf');
});

Using binary data from Mongo collection as image source

I have an express app, storing data in mongo, using Jade as the view engine. I have a simple route that gets the docs in a particular collection, each doc corresponding to a product. The image is base64 encoded. When I try and render as an image though it doesn't work
My route is
exports.index = function(req, res){
mongo.getProducts(function(data) {
res.render('consumer/index', {user: req.session.user, products: data});
});
};
The function that calls is
exports.getProducts = function(callback) {
Product.find().exec(function(err, products){
return callback(products);
});
};
and then my Jade file has the following code
each val in products
img(src="data:image/png;base64,'+#{val.image.data}+'", alt='Image', style="width: 20px; height: 20px")
Looking at the doc directly in Mongo (via robomongo) I get this
I don't know what I'm missing, because in another file I use jQuery datatables to show the documents, and the same approach there correctly renders the image, here is a snippet of the datatables code
"aoColumns": [
{"mData": "name"},
{"mData": "price"},
{"mData": "category"},
{"mData": "description"},
{"mData": "image.data", "mRender": function ( data, type, full ) {
return '<img src="data:image/png;base64,'+data+'", style="width: 20px; height: 20px"></>'}},
{"mData": "promoted"},
{"mData": null}
]
The problem is val.image.data doesn't provide a base64 string but a buffer. So, you have to convert it first. This is how I made it work:
Product.findById('559f6e08b090ca5c5ce6942b', function(err, result) {
if (err) throw (err);
var thumb = new Buffer(result.image.data).toString('base64');
res.render('index', { title: 'Express', img: thumb});
});
Also, there's a small issue on your frontend jade code, it should be:
img(src="data:image/jpeg;base64,#{img}") //No + and ''
Note: You could get away with this for small thumbnails or such but it is not the recommended approach due to a number of reasons (such as the 16MB limit). You are much better off using GridFS. More at http://docs.mongodb.org/manual/core/gridfs

Phantomjs node set header,footer

How can I set page header and footer using phantomjs with node, basically I'm generating pdf from html and I'm willing to add my header and footer from node, I have tries with following but pdf is not showing any data, and I'm reading empty page and willing to add header and footer, here is my Code:
// Load ejs template
fs.readFile(__dirname + '/../pdf' + pdfpath, 'utf8', function (err, data) {
// Render the page to variable.
var html = ejs.render(data, pdfJSON);
// Set this html as the content for the pdf file.
page.set('content', html);
page.set('generatePDF', function (pageNum, numPages) {
if (pageNum == 1) {
return "";
}
return "<h1>Header <span style='float:right'>" + pageNum + " / " + numPages + "</span></h1>";
});
page.set('paperSize', {
width: 1200,
height: 1500,
header: {
height: "1cm",
contents: phantom.generatePDF
}
});
console.log(phantom.generatePDF);//return undifned
page.set('paperSize', {
width: 1200,
height: 1500
});
// Generate the pdf.
var fileName = __dirname + '/pdfdata/' + f.formType + f.formId + '.pdf';
page.render(fileName, cb);
});
How I can resolve this?
Take a look to these example:
https://github.com/ariya/phantomjs/blob/master/examples/printheaderfooter.js
Edit: Sorry, didn't noticed you asked for Node, you can find some solutions and answers here also:
Footer's contents don't seem to work

Resources