【问题标题】:Populating a PDFKit Image from Firebase Storage while in a Firebase Function?在 Firebase 函数中从 Firebase 存储填充 PDFKit 图像?
【发布时间】:2018-10-02 18:22:18
【问题描述】:

我一直在尝试从 PDFKit 填充 PDFDoc 中的图像,但无法使其正常工作。使用下面的功能时,我在 Firebase 控制台-功能-日志中收到以下错误。该文件以“image/png”类型存储在 Firebase 存储中。名称只是一个字符串。我尝试将“.PNG”附加到名称后,我收到了同样的错误。我包含了整个函数文件,因为也许有更可接受的方法来处理这个?在 Firebase 函数中,我应该如何将 PDF 从 Firebase Storage 插入 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);
    });
});

【问题讨论】:

    标签: firebase google-cloud-functions pdfkit


    【解决方案1】:

    这就是我最终解决这个问题的方法。关键项目是将响应编码设置为“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);
            });
    
        });
    
    }
    

    【讨论】:

    • 我很欣赏这篇文章。多年来我一直在使用 pdftk,但以前从未使用过 FireStore。您能否分享如何/如果您必须安装二进制文件以通过云功能使用 pdftk,以及您如何存储文件的代码? (您是否使用临时目录,然后将其保存在其他地方等?)谢谢。
    • 嘿,所以我在 Node.js 中运行了这段代码,它在第一个 Promise(async(resolve,reject) => {} 时给了我一个解析错误,说这是一个预期的令牌......有什么想法吗?
    猜你喜欢
    • 1970-01-01
    • 2018-10-15
    • 2019-09-07
    • 2020-07-04
    • 2016-09-28
    • 2019-12-20
    • 1970-01-01
    • 2019-10-15
    • 1970-01-01
    相关资源
    最近更新 更多