Pdfkit: Missing information about how to get the content of a file into a stream

Created on 6 May 2014  路  8Comments  路  Source: foliojs/pdfkit

I need to base64 encode the content of a pdf to send it by email, but I cant find any information on how to get the content created by pdfkit to a string for conversion.
In my particular case, I've managed to create a stream and write the content to a file. But how do I know it is all done and I can safely read from the file?

Could you add some comments about this to the docs?

Most helpful comment

I would use concat-stream to turn the stream into a buffer, and then use the buffer's toString method to get base64. That way there is no need to make a temporary file at all.

var concat = require('concat-stream');

pdf.pipe(concat(function(buffer) {
    var string = buffer.toString('base64');
    // do something with the string here...
}));

All 8 comments

I would use concat-stream to turn the stream into a buffer, and then use the buffer's toString method to get base64. That way there is no need to make a temporary file at all.

var concat = require('concat-stream');

pdf.pipe(concat(function(buffer) {
    var string = buffer.toString('base64');
    // do something with the string here...
}));

Thank you for that nice solution!

I'm having trouble understanding how to use this. I need to pass the completed PDF back to an express controller to be able to render using res.send(myPDF). I'm creating the pdf in a service layer I created and want to pass it back to using callbacks when the PDF is done being created.

I've got the code above but I assume I still need a stream.on('finish') to deal with when the stream is done so I can pass the result to my callback. Is this correct? Or do I return the string within the '//do something with the string here...'?

Sounds like you just want to send the PDF to an HTTP response? To do that, you can just pdfdoc.pipe(response). If you actually need a buffer of the whole pdf for whatever reason, the above code should work. No need for a stream.on('finish') or anything since the concat-stream module I used above handles that for you. But if you're just sending the PDF to an HTTP response it is better to just pipe it directly there since buffering the whole thing in memory is wasteful.

Thanks for the quick response. I'm actually wanting to send the 'pdf' as the result in a callback of a function.

I'm trying:

doc.pipe(concat(function (buffer) {
  return onDone(null, buffer);
}));

In my pdf service layer which seems to work, and rendering it to browser from express like this:

PDFhelper.renderPDF(myDocObject, function (err, pdf) {
    console.log('rendering final doc.');
    res.end(pdf);
  });

However, adding anything other than an image or page to my doc causes it to not work (and I'm not sure if this is related to streams or something else. All worked before the update).

WORKS:

  doc.image('public/images/logo_site.png', 300, 0);
  //doc.text('Some Text: ', 30, 160);
  doc.image('public/images/logo_site.png', 100, 0);
  doc.addPage();

DOES NOT WORK:

  doc.text('Some Test: ', 30, 160);
  doc.addPage();

Is the callback to concat-stream called at all when it doesn't work? Make sure you're calling doc.end() when you're done adding content or the stream won't be finalized. This needs to be done whether you pipe directly to the response or to a buffer.

Also, why not have your renderPDF function just return the PDF document so you can pipe it directly? For example:

res.pipe(PDFhelper.renderPDF(myDocObject));

Or if renderPDF is async,

PDFhelper.renderPDF(myDocObject, function (err, pdf) {
   pdf.pipe(res);
});

Another option is to pass the response into your renderPDF function.

Any of these should work, it's just better to pipe the pdf directly when you can because it will save a lot of memory.

What might I be missing?

I pdfdoc.pipe(response) a pdf document but when in the angular controller I can't handle the buffer:
I get an array: data[0]=% data[1]=P data[2]=D ... and so on. So I have the stream on the client as I see it when debugging but can't create the pdf file out of it. I get a corrputed PDF file...
I'm using this approach to automatically download the pdf file:

hiddenElement.href = 'data:application/pdf,' + encodeURI(data);

I can't figure it out, already checked and tried plenty of stackoverflow's posts...

pdfstream

My code

code_handlepdfstream

I would use concat-stream to turn the stream into a buffer, and then use the buffer's toString method to get base64. That way there is no need to make a temporary file at all.

var concat = require('concat-stream');

pdf.pipe(concat(function(buffer) {
    var string = buffer.toString('base64');
    // do something with the string here...
}));

Thank you! This was exactly what I was looking for!

Was this page helpful?
0 / 5 - 0 ratings