Node js,将pdfkit管道传输到内存流

Node js, piping pdfkit to a memory stream

我在我的节点服务器上使用 pdfkit (https://github.com/devongovett/pdfkit),通常创建 pdf 文件,然后将它们上传到 s3。 问题是 pdfkit 示例将 pdf 文档通过管道传输到节点写入流中,该节点写入流将文件写入磁盘,我按照示例并正常工作,但是我现在的要求是将 pdf 文档通过管道传输到内存流而不是保存它在磁盘上(无论如何我正在上传到 s3)。 我遵循了一些节点内存流程序,但其中 none 似乎与我一起使用 pdf 管道,我可以将字符串写入内存流。 所以我的问题是:如何将 pdf 工具包输出通过管道传输到内存流(或类似的东西),然后将其作为对象读取以上传到 s3?

var fsStream = fs.createWriteStream(outputPath + fileName); 
doc.pipe(fsStream);

提前致谢。

您可以尝试这样的操作,然后在 end 事件中将其上传到 S3。

var doc = new pdfkit();

var MemoryStream = require('memorystream');
var memStream = new MemoryStream(null, {
   readable : false
});

doc.pipe(memStream);

doc.on('end', function () {
   var buffer = Buffer.concat(memStream.queue);
   awsservice.putS3Object(buffer, fileName, fileType, folder).then(function () { }, reject);
})

无需使用中间内存流1 – 只需将 pdfkit 输出流直接通过管道传输到 HTTP 上传流中即可。

根据我的经验,AWS SDK 在处理流时很垃圾,所以我通常使用 request

var upload = request({
    method: 'PUT',
    url: 'https://bucket.s3.amazonaws.com/doc.pdf',
    aws: { bucket: 'bucket', key: ..., secret: ... }
});

doc.pipe(upload);

1 - 事实上,通常不希望使用内存流,因为这意味着将整个内容缓冲在 RAM 中,这正是流应该避免的!

@bolav 的回答对我尝试使用 pdfmake 而不是 pdfkit 进行了调整。首先,您需要使用 npmyarn.

memorystream 添加到您的项目中
const MemoryStream = require('memorystream');
const PdfPrinter = require('pdfmake');
const pdfPrinter = new PdfPrinter();
const docDef = {};
const pdfDoc = pdfPrinter.createPdfKitDocument(docDef);
const memStream = new MemoryStream(null, {readable: false});
const pdfDocStream = pdfDoc.pipe(memStream);
pdfDoc.end();
pdfDocStream.on('finish', () => {
  console.log(Buffer.concat(memStream.queue);
});

2020 年的更新答案。不需要引入新的内存流,因为 "PDFDocument instances are readable Node streams"。

您可以使用 get-stream 包来轻松等待文档完成,然后再将结果传回给调用者。 https://www.npmjs.com/package/get-stream

const PDFDocument = require('pdfkit')
const getStream = require('get-stream')

const pdf = () => {
  const doc = new PDFDocument()
  doc.text('Hello, World!')
  doc.end()
  return await getStream.buffer(doc)
}


// Caller could do this:
const pdfBuffer = await pdf()
const pdfBase64string = pdfBuffer.toString('base64')

如果您的需求不同,则不必 return 缓冲区。 get-stream 自述文件提供了其他示例。

我的代码 return pdfkit 的 base64:

import * as PDFDocument from 'pdfkit'
import getStream from 'get-stream'

const pdf = {
  createPdf: async (text: string) => {
    const doc = new PDFDocument()
    doc.fontSize(10).text(text, 50, 50)
    doc.end()

    const data = await getStream.buffer(doc)
    let b64 = Buffer.from(data).toString('base64')
    return b64
  }
}

export default pdf