在 Firebase 函数中从 Firebase 存储填充 PDFKit 图像?
Populating a PDFKit Image from Firebase Storage while in a Firebase Function?
我一直在尝试从 PDFKit 填充 PDFDoc 中的图像,但无法让它工作。使用下面的函数时,Firebase 控制台函数日志中出现以下错误。该文件以 "image/png" 类型存储在 Firebase 存储中。名称只是一个字符串。我尝试在名称后附加“.PNG”,但我收到了同样的错误。我包含了整个函数文件,因为也许有更可接受的方法来处理这个问题?在 Firebase 函数中,我应该如何将 PDF 从 Firebase 存储插入 PDFDoc?谢谢。
获取文档时出错:错误:未知的图像格式。
在 Function.PDFImage.open (/user_code/node_modules/pdfkit/js/image.js:43:15)
在 PDFDocument.openImage (/user_code/node_modules/pdfkit/js/mixins/images.js:102:26)
在 PDFDocument.image (/user_code/node_modules/pdfkit/js/mixins/images.js:30:24)
在 /user_code/lib/index.js:71:48
在 QuerySnapshot.forEach (/user_code/node_modules/firebase-admin/node_modules/@google-cloud/firestore/src/reference.js:1012:16)
在 /user_code/lib/index.js:24:31
在 process._tickDomainCallback (internal/process/next_tick.js:135:7)
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import * as firebase from 'firebase/app';
import * as PDFDocument from 'pdfkit';
admin.initializeApp(functions.config().firebase);
export const genPdf = functions.https.onRequest((request, response) => {
const bucket = admin.storage().bucket("decteac2-3hcec.appspot.com");
const text = request.query.text;
const pdfdoc = new PDFDocument({ autoFirstPage: false });
pdfdoc.info['Title'] = text + ".pdf";
let x = 5;
let y = 5;
pdfdoc.pipe(response);
const docRef = admin.firestore().collection("cxforms").doc(text);
docRef.get().then(function (doc) {
if (doc.exists) {
const pagesRef = admin.firestore().collection("pages").where("formKey", "==", text).orderBy("pageno");
pagesRef.get().then(function (querySnapshot) {
let cnt = 1;
querySnapshot.forEach(function (page) {
pdfdoc.addPage({ margin: 0 });
x = 5;
y = 5;
pdfdoc.moveTo(x, y)
.lineTo(607, 5)
.lineTo(607, 787)
.lineTo(5, 787)
.lineTo(x, y)
.stroke();
for (let i = 0; i < page.data().tables.length; i++) {
const table = page.data().tables[i];
y = y + 8.5; // margin
var tableWidth = 5;
for (let p = 0; p < table.cols.length; p++) {
tableWidth = tableWidth + (table.cols[p] * .82);
}
var offset = (597 - tableWidth) / 2;
for (let j = 0; j < table.rows.length; j++) {
const row = table.rows[j];
x = 10 + offset;
for (let k = 0; k < row.cells.length; k++) {
const cell = row.cells[k];
const colwidth = table.cols[k];
var height = 22.2;
for (let l = 0; l < cell.cellels.length; l++) {
const cellEl = cell.cellels[l];
if (cellEl.type === "Text") {
pdfdoc.text(cellEl.text, x + 1, y + 7);
} else if (cellEl.type == "Image") {
const filename = cellEl.storageid;
const file = bucket.file(filename);
const bucketFileStream = file.createWriteStream();
const buffer = new Buffer([1000000]);
bucketFileStream.write(buffer);
bucketFileStream.end();
pdfdoc.image(buffer, x, y);
}
}
if (height < 20) {
height = 20;
}
pdfdoc.moveTo(x, y)
.lineTo(x + (colwidth * .82), y)
.lineTo(x + (colwidth * .82), y + height)
.lineTo(x, y + height)
.lineTo(x, y)
.stroke();
x = x + (colwidth * .82);
}
y = y + height;
}
}
cnt++;
});
pdfdoc.end();
}).catch(function (error) {
console.log("Error getting documents: ", error);
})
} else {
console.log("No such document!");
}
}).catch(function (error) {
console.log("Error gettting documents: ", error);
});
});
我是这样解决这个问题的。关键项目是将响应编码设置为 'base64' 以调用 Firestorage。另一项是使用 async 和 await 以等待每个单元格元素图像填充 pdfdoc,然后再继续下一个要呈现的单元格元素。
if (cellEl.type == "Image") {await toBase64(cellEl.url, x, y, pdfdoc);}
function toBase64(url, x, y, pdfdoc) {
return new Promise(async(resolve, reject) => {
var req = await https.get(url, (res) => {
res.setEncoding('base64');
let body = "data:" + res.headers["content-type"] + ";base64,";
res.on('data', (d) => {
body += d;
});
res.on('end', () => {
pdfdoc.image(body, x, y);
resolve(res);
});
});
req.on('error', err => {
console.error('error!');
reject(err);
});
});
}
我一直在尝试从 PDFKit 填充 PDFDoc 中的图像,但无法让它工作。使用下面的函数时,Firebase 控制台函数日志中出现以下错误。该文件以 "image/png" 类型存储在 Firebase 存储中。名称只是一个字符串。我尝试在名称后附加“.PNG”,但我收到了同样的错误。我包含了整个函数文件,因为也许有更可接受的方法来处理这个问题?在 Firebase 函数中,我应该如何将 PDF 从 Firebase 存储插入 PDFDoc?谢谢。
获取文档时出错:错误:未知的图像格式。 在 Function.PDFImage.open (/user_code/node_modules/pdfkit/js/image.js:43:15) 在 PDFDocument.openImage (/user_code/node_modules/pdfkit/js/mixins/images.js:102:26) 在 PDFDocument.image (/user_code/node_modules/pdfkit/js/mixins/images.js:30:24) 在 /user_code/lib/index.js:71:48 在 QuerySnapshot.forEach (/user_code/node_modules/firebase-admin/node_modules/@google-cloud/firestore/src/reference.js:1012:16) 在 /user_code/lib/index.js:24:31 在 process._tickDomainCallback (internal/process/next_tick.js:135:7)
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import * as firebase from 'firebase/app';
import * as PDFDocument from 'pdfkit';
admin.initializeApp(functions.config().firebase);
export const genPdf = functions.https.onRequest((request, response) => {
const bucket = admin.storage().bucket("decteac2-3hcec.appspot.com");
const text = request.query.text;
const pdfdoc = new PDFDocument({ autoFirstPage: false });
pdfdoc.info['Title'] = text + ".pdf";
let x = 5;
let y = 5;
pdfdoc.pipe(response);
const docRef = admin.firestore().collection("cxforms").doc(text);
docRef.get().then(function (doc) {
if (doc.exists) {
const pagesRef = admin.firestore().collection("pages").where("formKey", "==", text).orderBy("pageno");
pagesRef.get().then(function (querySnapshot) {
let cnt = 1;
querySnapshot.forEach(function (page) {
pdfdoc.addPage({ margin: 0 });
x = 5;
y = 5;
pdfdoc.moveTo(x, y)
.lineTo(607, 5)
.lineTo(607, 787)
.lineTo(5, 787)
.lineTo(x, y)
.stroke();
for (let i = 0; i < page.data().tables.length; i++) {
const table = page.data().tables[i];
y = y + 8.5; // margin
var tableWidth = 5;
for (let p = 0; p < table.cols.length; p++) {
tableWidth = tableWidth + (table.cols[p] * .82);
}
var offset = (597 - tableWidth) / 2;
for (let j = 0; j < table.rows.length; j++) {
const row = table.rows[j];
x = 10 + offset;
for (let k = 0; k < row.cells.length; k++) {
const cell = row.cells[k];
const colwidth = table.cols[k];
var height = 22.2;
for (let l = 0; l < cell.cellels.length; l++) {
const cellEl = cell.cellels[l];
if (cellEl.type === "Text") {
pdfdoc.text(cellEl.text, x + 1, y + 7);
} else if (cellEl.type == "Image") {
const filename = cellEl.storageid;
const file = bucket.file(filename);
const bucketFileStream = file.createWriteStream();
const buffer = new Buffer([1000000]);
bucketFileStream.write(buffer);
bucketFileStream.end();
pdfdoc.image(buffer, x, y);
}
}
if (height < 20) {
height = 20;
}
pdfdoc.moveTo(x, y)
.lineTo(x + (colwidth * .82), y)
.lineTo(x + (colwidth * .82), y + height)
.lineTo(x, y + height)
.lineTo(x, y)
.stroke();
x = x + (colwidth * .82);
}
y = y + height;
}
}
cnt++;
});
pdfdoc.end();
}).catch(function (error) {
console.log("Error getting documents: ", error);
})
} else {
console.log("No such document!");
}
}).catch(function (error) {
console.log("Error gettting documents: ", error);
});
});
我是这样解决这个问题的。关键项目是将响应编码设置为 'base64' 以调用 Firestorage。另一项是使用 async 和 await 以等待每个单元格元素图像填充 pdfdoc,然后再继续下一个要呈现的单元格元素。
if (cellEl.type == "Image") {await toBase64(cellEl.url, x, y, pdfdoc);}
function toBase64(url, x, y, pdfdoc) {
return new Promise(async(resolve, reject) => {
var req = await https.get(url, (res) => {
res.setEncoding('base64');
let body = "data:" + res.headers["content-type"] + ";base64,";
res.on('data', (d) => {
body += d;
});
res.on('end', () => {
pdfdoc.image(body, x, y);
resolve(res);
});
});
req.on('error', err => {
console.error('error!');
reject(err);
});
});
}