Как сгенерировать pdf с помощью pdfmake и сохранить его в хранилище Firebase с помощью облачных функций Firebase

Я разрабатываю приложение в firebase. Когда заказ создан, я хочу создать счет-фактуру. Я реализовал эту функцию, но что-то не так с URL-адресами, потому что PDF-файл создан, но, как вы можете видеть на изображении, URL-адрес для его открытия неверен.

Это мой код в облачной функции index.js:

'use strict';

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const nodemailer = require('nodemailer');
//...

var PdfPrinter = require('pdfmake');
const fs = require('fs');

var fonts = {
  Courier: {
    normal: 'Courier',
    bold: 'Courier-Bold',
    italics: 'Courier-Oblique',
    bolditalics: 'Courier-BoldOblique'
  },
  Helvetica: {
    normal: 'Helvetica',
    bold: 'Helvetica-Bold',
    italics: 'Helvetica-Oblique',
    bolditalics: 'Helvetica-BoldOblique'
  },
  Times: {
    normal: 'Times-Roman',
    bold: 'Times-Bold',
    italics: 'Times-Italic',
    bolditalics: 'Times-BoldItalic'
  },
  Symbol: {
    normal: 'Symbol'
  },
  ZapfDingbats: {
    normal: 'ZapfDingbats'
  }
};

exports.generateInvoice = functions.database.ref('/pedidos/{documentId}').onCreate((snap, context) => {
  return (async () => {
    var docDefinition = {
      pageSize: 'A4',
      pageOrientation: 'portrait',
      content: [
        //Cabecera
        { image: 'img/logo.png', width: 90, alignment: 'left' },
        { text: `Pedido${snap.key}`, fontSize: 32, margin: [0, 8, 0, 0] }
      
        //Body
      ],
      defaultStyle: {
        font: 'Helvetica'
      }
    };
    console.log("Doc defined okey");

    const pdfName = snap.key + ".pdf";
    const fileName = "pedidos/" + pdfName;
    const myPDFfile = admin.storage().bucket().file(fileName);

    var printer = new PdfPrinter(fonts);
    var pdfDoc = printer.createPdfKitDocument(docDefinition);
    pdfDoc.pipe(myPDFfile.createWriteStream());
    pdfDoc.end();

  })().then(() => {

  }).catch (err => {
    console.log("An error has ocurred " + err);
  });
});

Как видите, PDF-файл создан правильно, но URL-адрес неверный, и я не могу его открыть.

введите здесь описание изображения

Буду очень благодарен, если мне кто-нибудь поможет.


person Emili Bellot Pulido    schedule 14.05.2021    source источник


Ответы (1)


Это известная проблема при загрузке файлов в облачное хранилище через Admin SDK, см. https://github.com/firebase/firebase-admin-node/issues/694.

Как вы прочтете, есть в основном два возможных подхода:

  • Используйте метод getSignedUrl(), чтобы получить подписанный URL (который позволяет ограниченное время доступ к файлу) и сохраните его где-нибудь, например. в базе данных реального времени или в Firestore. Поскольку он имеет ограниченный срок службы, вам, возможно, придется регулярно продлевать его в зависимости от ваших функциональных требований, например, с помощью запланированной облачной функции.
  • Добавьте значение firebaseStorageDownloadTokens в метаданные файла. Хотя кажется, что это работает (см. код ниже), его также не рекомендуется использовать, поскольку это не официальная функция Google Cloud Storage, см. здесь

Если вы хотите использовать второй вариант (несмотря на то, что он кажется нерекомендуемым), вам поможет следующее:

const pdfDoc = printer.createPdfKitDocument(docDefinition);
pdfDoc.pipe(myPDFfile.createWriteStream());

pdfDoc.on('end', async function () {
   const uniqueId = admin.firestore().collection("_").doc().id;
   await myPDFfile.setMetadata({
        metadata: {
           firebaseStorageDownloadTokens: uniqueId,
        }
   });
});

pdfDoc.end();

Однако я бы рекомендовал первый подход с методом getSignedUrl().

person Renaud Tarnec    schedule 14.05.2021
comment
Красиво, попробую. Спасибо!!! - person Emili Bellot Pulido; 14.05.2021
comment
Если я работаю с базой данных в реальном времени, мне нужно это изменить? admin.firestore().collection("_").doc().id - person Emili Bellot Pulido; 14.05.2021
comment
Это фактически создает уникальный идентификатор, используя SDK администратора Firestore, который вы импортируете в верхней части своего CF. Это не требует никаких затрат. Вы можете очень хорошо использовать библиотеку uuid, как указано на страницах GitHub, ссылки на которые есть в моем ответе. - person Renaud Tarnec; 14.05.2021