Reputation: 1442
Here is a one of PDFMake's code snippet to create pdf file:
var pdfDoc = printer.createPdfKitDocument(docDefinition);
pdfDoc.pipe(fs.createWriteStream('pdfs/absolute.pdf'));
pdfDoc.end();
and here is one of the attachment option in NodeMailer:
{
// stream as an attachment
filename: 'text4.txt',
content: fs.createReadStream('file.txt')
}
I am able to create pdf and save it to a file in a directory and attach that saved file in the e-mail but I want to directly send the output of pdf to the attachment content of e-mail without saving the pdf output to a file.
I tried to understand nodejs pipe and stream features but couldn't understand them to meet my requirement. I think it should be possible through stream and pipe but don't know how to achieve.
I want to prevent saving of pdf output to file because there can be multiple users using the functionality of creating pdf file and sending e-mail. There can be a situation when a pdf file created by one user will be overwritten by another user.
Upvotes: 6
Views: 14287
Reputation: 31
I was able to get it to work using a buffer, and ending the buffer AFTER the email was sent with the attachment from PDFMake. If you end the buffer before the email is sent it will not work:
const printer = new pdfMakePrinter(fontDescriptors);
const doc = printer.createPdfKitDocument(docDefinition);
let buffers = [];
doc.on('data', buffers.push.bind(buffers));
doc.on('end', () => {
let pdfData = Buffer.concat(buffers);
let mailOptions = {
from: '"John Doe" <[email protected]>', // sender address
to: '[email protected]', // list of receivers
subject: 'stuff' // Subject line
text: '',
html: '', // html body
attachments: [{
filename: 'attachment.pdf',
content: pdfData
}]
};
transporter.sendMail(mailOptions, (error, info) => {
if (error) {
return console.log(error);
}
console.log('Message sent: %s', info.messageId);
console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info));
});
});
//end buffer
doc.end();
Upvotes: 3
Reputation:
var pdfMake = require('pdfmake/build/pdfmake.js');
var pdfFonts = require('pdfmake/build/vfs_fonts.js');
pdfMake.vfs = pdfFonts.pdfMake.vfs;
//var base64 = require('base64-js');
var docDefinition = function(json) {
return {
content: [
'PARAGRAPH 1',
'paragraph 2', {
columns: [
'first column is a simple text', {
stack: [
// second column consists of paragraphs
'paragraph A',
'paragraph B',
'these paragraphs will be rendered one below another inside the column'
],
fontSize: 15
}]}]};};
const pdfDocGenerator = pdfMake.createPdf(docDefinition);
pdfDocGenerator.getBuffer((pdfBuffer) => {
// HERE YOU HAVE THE PDF BUFFER
//var pdfbase64 = base64.fromByteArray(buffer);
//console.log("pdfDocGenerator.getBuffer OK" + pdfbase64);
fs.writeFileSync('foo.pdf', buffer);
}
Upvotes: 0
Reputation: 164
Here's what I did. It works in a Meteor app.
Client Side:
var docDefinition = {
content: [
'First paragraph'
]
};
var data;
pdfMake.createPdf(docDefinition).getBase64(function(encodedString) {
data = encodedString;
Meteor.call("sendPDFEmail", data);
});
Server Side
sendPDFEmail: function(thepdf){
Email.send({
to: "receiver",
from: "sender",
subject: "Test",
html: "text",
attachments: [
{
filename: "test.pdf",
type: "application/pdf",
content: Buffer.from(thepdf, 'base64')
}
]
});
},
Upvotes: 0
Reputation: 547
you could instead of pipe, pass the entire pdfdoc
to the attachment
var pdfDoc = printer.createPdfKitDocument(docDefinition);
pdfDoc.end();
and then:
attachments: {
// stream as an attachment
filename: 'text4.pdf',
content: pdfDoc
}
Upvotes: 12