ExpressJS и PDFKit - создайте PDF в памяти и отправьте клиенту для загрузки - PullRequest
0 голосов
/ 25 сентября 2019

В моем api маршрутизаторе есть функция под названием generatePDF, целью которой является использование модуля PDFKit для генерации PDF-файла в памяти и отправки клиенту для загрузки вместо отображения только.

In api.js:

var express = require('express');
var router = express.Router();

const PDFDocument = require('pdfkit');

router.get('/generatePDF', async function(req, res, next) {
    var myDoc = new PDFDocument({bufferPages: true});
    myDoc.pipe(res);
    myDoc.font('Times-Roman')
         .fontSize(12)
         .text(`this is a test text`);
    myDoc.end();
    res.writeHead(200, {
        'Content-Type': 'application/pdf',
        'Content-disposition': 'attachment;filename=test.pdf',
        'Content-Length': 1111
    });
    res.send( myDoc.toString('base64'));
});

module.exports = router;

Это не работает.Сообщение об ошибке: (node:11444) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client.

Как мне решить проблему и заставить ее работать?

Кроме того, уместным вопросом будет то, как я могу отделить бизнес-логику генерации PDF.от роутера и связать их?

Ответы [ 2 ]

0 голосов
/ 25 сентября 2019

Вы можете использовать поток BLOB-объектов следующим образом.

ссылка: https://pdfkit.org/index.html

const PDFDocument = require('pdfkit');

const blobStream  = require('blob-stream');

// create a document the same way as above

const doc = new PDFDocument;

// pipe the document to a blob

const stream = doc.pipe(blobStream());

// add your content to the document here, as usual

doc.font('fonts/PalatinoBold.ttf')
   .fontSize(25)
   .text('Some text with an embedded font!', 100, 100);

// get a blob when you're done
doc.end();
stream.on('finish', function() {
  // get a blob you can do whatever you like with
  const blob = stream.toBlob('application/pdf');

  // or get a blob URL for display in the browser
  const url = stream.toBlobURL('application/pdf');
  iframe.src = url;
});

передать все ваши PDF-данные в ваш BLOB-объект, а затем записать его в файл или URL-адрес.или вы можете сохранить PDF непосредственно в облачном хранилище, например, в хранилище Firebase, и отправить ссылку на скачивание клиенту.

Если вы хотите динамически генерировать PDF, то вы также можете попробовать библиотеку html-pdf в узле, который позволяет вам создаватьPDF из шаблона HTML и добавить динамические данные в нем.Также он более надежен, чем pdfkit https://www.npmjs.com/package/html-pdf Также обратитесь по этой ссылке Создайте pdf-файл с помощью pdfkit и отправьте его в браузер в nodejs-expressjs

0 голосов
/ 25 сентября 2019

Полное решение.

var express = require('express');
var router = express.Router();

const PDFDocument =  require('pdfkit');

router.get('/generatePDF', async function(req, res, next) {
var myDoc = new PDFDocument({bufferPages: true});

let buffers = [];
myDoc.on('data', buffers.push.bind(buffers));
myDoc.on('end', () => {

    let pdfData = Buffer.concat(buffers);
    res.writeHead(200, {
    'Content-Length': Buffer.byteLength(pdfData),
    'Content-Type': 'application/pdf',
    'Content-disposition': 'attachment;filename=test.pdf',})
    .end(pdfData);

});

myDoc.font('Times-Roman')
     .fontSize(12)
     .text(`this is a test text`);
myDoc.end();
});

module.exports = router;
...