我需要制作一个包含用户内容的pdf文件并将其发送回去。我选择了 pdfmake ,因为这样可以制作表格。 我使用 Koa .js;
router.post('/pdf', koaBody(), async ctx => {
const doc = printer.createPdfKitDocument(myFunctionGeneratePDFBody(ctx.request.body));
doc.pipe(ctx.res, { end: false });
doc.end();
ctx.res.writeHead(200, {
'Content-Type': 'application/pdf',
"Content-Disposition": "attachment; filename=document.pdf",
});
ctx.res.end();
});
并得到一个错误
Error [ERR_STREAM_WRITE_AFTER_END]: write after end
at write_ (_http_outgoing.js:572:17)
at ServerResponse.write (_http_outgoing.js:567:10)
at PDFDocument.ondata (_stream_readable.js:666:20)
at PDFDocument.emit (events.js:182:13)
at PDFDocument.EventEmitter.emit (domain.js:442:20)
at PDFDocument.Readable.read (_stream_readable.js:486:10)
at flow (_stream_readable.js:922:34)
at resume_ (_stream_readable.js:904:3)
at process._tickCallback (internal/process/next_tick.js:63:19)
但是保存在中间文件中并发送其工作...
router.post('/pdf', koaBody(), async ctx => {
await new Promise((resolve, reject) => {
const doc = printer.createPdfKitDocument(generatePDF(ctx.request.body));
doc.pipe(fs.createWriteStream(__dirname + '/document.pdf'));
doc.end();
doc.on('error', reject);
doc.on('end', resolve);
})
.then(async () => {
ctx.res.writeHead(200, {
'Content-Type': 'application/pdf',
'Content-Disposition': 'attachment; filename=document.pdf',
});
const stream = fs.createReadStream(__dirname + '/document.pdf');
return new Promise((resolve, reject) => {
stream.pipe(ctx.res, { end: false });
stream.on('error', reject);
stream.on('end', resolve);
});
});
ctx.res.end();
});
答案 0 :(得分:0)
避免使用writeHead
,请参阅https://koajs.com/#response。
这样做:
ctx.attachment('file.pdf');
ctx.type =
'application/pdf';
const stream = fs.createReadStream(`${process.cwd()}/uploads/file.pdf`);
ctx.ok(stream); // from https://github.com/jeffijoe/koa-respond
答案 1 :(得分:0)
我遇到了同样的问题,您的问题帮助了我,我已经弄清楚了这个问题:您正在立即结束响应/信息流,尽管尚未完全写好。问题是doc.end()
会在写入完成之前立即返回。诀窍是让您的文档在流完成时结束流(因此不再end: false
)并等待此事件,例如使用Promise。
固定代码如下:
router.post('/pdf', koaBody(), async ctx => {
const doc = printer.createPdfKitDocument(myFunctionGeneratePDFBody(ctx.request.body));
doc.pipe(ctx.res);
doc.end();
ctx.res.writeHead(200, {
'Content-Type': 'application/pdf',
"Content-Disposition": "attachment; filename=document.pdf",
});
return new Promise(resolve => ctx.res.on('finish', resolve));
});