I am developing an application in firebase. When an order is created I want to generate its invoice. I have implemented the function, but something is wrong with the URLs because the pdf is created, but as you can see in the image the URL to open it is wrong.
This is my code in Cloud Function 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);
});
});
As you can see, the pdf is created correctly but the URL is wrong and I can't open it.
I would be very grateful if someone helped me.
This is a known problem when uploading files to Cloud Storage via the Admin SDK, see https://github.com/firebase/firebase-admin-node/issues/694.
As you will read there are mainly two possible approaches:
getSignedUrl()
method to get a signed URL (which allows limited time access to the file) and save it somewhere, e.g. in the Realtime Database or in Firestore. Since it has a limited life, you may have to renew it regularly depending on your functional requirements, for example via a scheduled Cloud Function.firebaseStorageDownloadTokens
value to the file metadata. While it seems to work (see the code below), it also seems to be not recommended because it is not an official Google Cloud Storage feature, see hereIf you want to use the second option (despite the fact it seems to be not recommended), the following would do the trick:
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();
I would recommend the first approach however, with the getSignedUrl()
method.