在Firebase功能中从Firebase存储中填充PDFKit图像?

Populating a PDFKit Image from Firebase Storage while in a Firebase Function?

我一直在尝试从PDFKit中填充PDFDoc中的图像,但无法使其正常工作。使用以下功能时,Firebase控制台功能日志中会出现以下错误。该文件以" image / png"类型存储在Firebase Storage中。名称只是一个字符串。我尝试在名称后附加" .PNG",但收到相同的错误。我包含了整个函数文件,因为也许有一种更可接受的方式来处理此问题?在使用Firebase功能时,如何从Firebase存储中将PDF插入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(内部/进程/next_tick.js:135:7)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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"){等待toBase64(cellEl.url,x,y,pdfdoc);}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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);
        });

    });

}