PDFMake has this method for streaming a generated PDF document :
const pdfDoc = printer.createPdfKitDocument(docDefinition, options);
pdfDoc.pipe(fs.createWriteStream('document.pdf')); // send to output stream
pdfDoc.end();
And fastify has this to stream things :
fastify.get('/streams', function (request, reply) {
const fs = require('fs')
const stream = fs.createReadStream('some-file', 'utf8')
reply.header('Content-Type', 'application/octet-stream')
reply.send(stream) // send from input stream
})
How are those two working together? Preferably, PDFMake should directly stream through fastify and not buffer the entire PDF before sending it.
For reference, with Koa (or Express), I would simply do :
app.use(async (ctx, next) => {
const pdfDoc = printer.createPdfKitDocument(docDefinition, options);
res.setHeader('content-type', 'application/pdf');
res.setHeader('content-disposition', req.headers['content-disposition'] || 'inline');
res.status(200);
pdfDoc.pipe(res);
pdfDoc.end();
});
However, I cannot do reply.send(pdfDoc)
.
Since PDFKit's PDFKit.PDFDocument
type seems to be a readable stream, I have tried
fastify.get('/streams', function (request, reply) {
const pdfDoc = printer.createPdfKitDocument(docDefinition, options);
reply.header('Content-Type', 'application/pdf');
reply.header('content-disposition', 'inline');
reply.send(pdfDoc); // "Failed to load PDF document"
})
I also tried PDFKit's solution of using blob-stream
:
fastify.get('/streams', function (request, reply) {
const pdfDoc = printer.createPdfKitDocument(docDefinition, options);
const stream = pdfDoc.pipe(blobStream());
reply.header('Content-Type', 'application/pdf');
reply.header('content-disposition', 'inline');
reply.send(stream); // "Failed to load PDF document"
pdfDoc.end();
})
There are no errors except in the browser.
This is my current solution :
fastify.get('/pdf', async (request, reply) => {
const pdfDoc = printer.createPdfKitDocument(...getDocumentDefinition(request));
const buffer = await new Promise((resolve, reject) => {
const chunks = [];
const stream = new Writable({
write: (chunk, _, next) => {
chunks.push(chunk);
next();
}
});
stream.once('error', (err) => reject(err));
stream.once('close', () => resolve(Buffer.concat(chunks)));
pdfDoc.pipe(stream);
pdfDoc.end();
});
reply.type('application/pdf').code(200).send(buffer);
})