22

I am using pdfkit to generate pdf file and i want to send this pdf file to browser.

But i am getting message "TypeError: listener must be a function", Also, file is getting generate in my parent directory which i don't want.

Can anyone explain me how to generate pdf file and send it to browser without storing it at parent directory?
I am using expressjs here.

My code

var PDFDocument = require('pdfkit');                      
var fs=require('fs');
doc = new PDFDocument();
doc.moveTo(300, 75)
   .lineTo(373, 301)
   .lineTo(181, 161)
   .lineTo(419, 161)
   .lineTo(227, 301)
   .fill('red', 'even-odd');  

var loremIpsum = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam in...';  

doc.y = 320;
doc.fillColor('black')
doc.text(loremIpsum, {
   paragraphGap: 10,
   indent: 20,
   align: 'justify',
   columns: 2
});  

doc.write('out.pdf');
res.download('out.pdf');
yuvi
  • 18,155
  • 8
  • 56
  • 93
Sachin
  • 2,321
  • 11
  • 31
  • 49
  • I have posted a new question. Need your suggestion. http://stackoverflow.com/questions/36802587/pdfkit-not-able-to-open-the-pdf-generated – Abhishek Kumar Apr 22 '16 at 20:29

2 Answers2

23

doc.write is the line causing the trouble, which is also a deprecated method so don't use it. Instead, use pipe to tell your doc where to stream the information, and remember to close it using doc.end(), i.e., like so:

doc = new PDFDocument();
doc.pipe( fs.createWriteStream('out.pdf') );

// rest of the code goes here...

doc.end();

Note that it's not important that doc.pipe() be at the top, it just makes sense to me (you can put it before or after doc.end(). It doesn't matter, it'll work just fine). Finally, note that you can use pipe to stream directly to a response, there's no need to create the file first and then download it, i.e.:

doc.pipe( res )
yuvi
  • 18,155
  • 8
  • 56
  • 93
  • 1
    still file is getting generate in local directory i want to send this file as download to browser. – Sachin May 13 '14 at 07:18
  • @SachinKumbharkar Yes sorry, I forgot to include the fs function in that last example. You still need it, just point it to the HTTP response instead of a local file – yuvi May 13 '14 at 07:20
  • 2
    Now i got error message uncaughtException: path must be a string. – Sachin May 13 '14 at 07:22
  • @SachinKumbharkar I'm not sure then. I have had no problem doing it here,are you running the latest version of pdfkit? Anyway, if nothing else, output it to a file using the first method I've shown and then send it to the response. Is that working for you? – yuvi May 13 '14 at 07:52
  • Yes it is working, Can you tell me how to generate pdf using html here? – Sachin May 13 '14 at 07:56
  • I want to generate html table in pdf – Sachin May 13 '14 at 07:57
  • I have posted my new question http://stackoverflow.com/questions/23625988/html-table-in-pdfkit-expressjs-nodejs – Sachin May 13 '14 at 08:18
  • 19
    not **doc.pipe( fs.createWriteStream(res) )** but **doc.pipe(res)** – Artur Czyżewski Dec 22 '15 at 21:36
  • I had to set headers to get it running. Like in this example: https://stackoverflow.com/questions/22887464/serve-dynamically-generated-pdf-with-remote-images-in-node-js – davidinteract Mar 29 '21 at 08:34
5

So Instead try Using

doc.pipe(res);

Rahil Lakhani
  • 412
  • 4
  • 7
  • i made this as a service on node, and pass data as parameter and pipe my data on response. did doc.pipe(res) and on my react side made an axios call - and abosorbed response in arraybuffer and wrote it to a blob. – Rahil Lakhani Apr 04 '17 at 10:40
  • Dont forget to end the stream using `doc.end()` – vs4vijay May 23 '17 at 12:06
  • Hi , I am stuck in a similar situation with the difference that my code will execute in AWS api gateway. I have written the description in this link , Would be of great help if anyone could take a look and help. https://stackoverflow.com/questions/57256887/invalid-pdf-structure-error-message-with-nodejs-pdfkit – NinjaDev Jul 29 '19 at 16:52