У меня проблема, когда мне нужно pipe()
создать документ для нескольких целей, в моем случае для HTTP-ответа и для вложения электронной почты с помощью node-mailer
. После первого использования во вложении к электронному письму ничего не передается в ответ (при вызове из клиента PDF имеет 0 байт).
Ответный контроллер:
const doc = await createPdf(course.name, lastRecordDate, ctx);
// Send a notificiation email with attachment
if (query.hasOwnProperty('sendEmail') && query.sendEmail === 'true') {
await sendNotificationEmail(doc, course, ctx);
}
doc.pipe(res);
res.contentType('application/pdf');
Функция отправки электронного письма:
async function sendNotificationEmail(doc: any, course: Course, ctx: Context) {
const attachment = {
filename: `${course.name}-certificate.pdf`,
contentType: 'application/pdf',
content: doc
};
return SMTPSendTemplateWithAttachments(
ctx,
['[email protected]'],
`${course.name}`,
'en-report-created',
{
firstName: ctx.user.firstName,
courseName: course.name
},
[attachment]
);
}
Если я удаляю функцию отправки электронного письма, PDF-файл обычно передается в ответ, и я могу загрузить его с клиента.
Я пытался найти способ клонировать поток (насколько я знаю, документ PDFKit является потоком), но безуспешно.
Любое решение будет действительно полезным.
Я решил проблему, используя два потока PassThrough
, в два из которых я передал PDFKit
документ Stream
, а затем в событии data
я записал chunks
в два отдельных буфера. В событии end
я отправляю данные по электронной почте, создаю новый поток PassThrough
и передаю его в ответ.
Вот код.
// Both PassThrough streams are defined before in order to use them in the createPdf function
streamCopy1 = new PassThrough();
streamCopy2 = new PassThrough();
const buffer1 = [];
const buffer2 = [];
streamCopy1
.on('data', (chunk) => {
buffer1.push(chunk);
})
.on('end', () => {
const bufferFinished = Buffer.concat(buffer1);
if (query.hasOwnProperty('sendEmail') && query.sendEmail === 'true') {
sendNotificationEmail(bufferFinished, course, ctx);
}
});
streamCopy2
.on('data', (chunk) => {
buffer2.push(chunk);
})
.on('end', () => {
const bufferFinished = Buffer.concat(buffer2);
const stream = new PassThrough();
stream.push(bufferFinished);
stream.end();
stream.pipe(res);
res.contentType('application/pdf');
});
Функция для создания PDF.
// function declaration
const doc = new pdfDocument();
doc.pipe(streamCopy1).pipe(streamCopy2);
// rest of the code
Решение на самом деле не самое приятное, любые предложения очень приветствуются.