Node js, piping pdfkit to a memory stream

后端 未结 5 1572
谎友^
谎友^ 2021-02-07 21:07

I am using pdfkit (https://github.com/devongovett/pdfkit) on my node server, typically creating pdf files, and then uploading them to s3. The problem is that pdfkit examples pip

相关标签:
5条回答
  • 2021-02-07 21:46

    A tweak of @bolav's answer worked for me trying to work with pdfmake and not pdfkit. First you need to have memorystream added to your project using npm or yarn.

    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);
    });
    
    0 讨论(0)
  • 2021-02-07 21:48

    My code to return a base64 for pdfkit:

    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
    
    0 讨论(0)
  • 2021-02-07 21:58

    There's no need to use an intermediate memory stream1 – just pipe the pdfkit output stream directly into a HTTP upload stream.

    In my experience, the AWS SDK is garbage when it comes to working with streams, so I usually use request.

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

    1 - in fact, it is usually undesirable to use a memory stream because that means buffering the entire thing in RAM, which is exactly what streams are supposed to avoid!

    0 讨论(0)
  • 2021-02-07 21:58

    An updated answer for 2020. There is no need to introduce a new memory stream because "PDFDocument instances are readable Node streams".

    You can use the get-stream package to make it easy to wait for the document to finish before passing the result back to your caller. 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')
    

    You don't have to return a buffer if your needs are different. The get-stream readme offers other examples.

    0 讨论(0)
  • 2021-02-07 21:59

    You could try something like this, and upload it to S3 inside the end event.

    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);
    })
    
    0 讨论(0)
提交回复
热议问题