使用@signpdf签署PDF遇TypeError: Cannot read properties of undefined (reading 'push')求助
使用@signpdf签署PDF时触发TypeError问题求助
场景与代码
通过Firebase Cloud Functions监听存储桶的对象完成事件,仅处理uploads文件夹下的PDF文件,使用@signpdf相关工具进行签名,代码如下:
const {onRequest} = require("firebase-functions/v2/https"); const {onObjectFinalized} = require("firebase-functions/v2/storage"); const admin = require('firebase-admin') const {initializeApp} = require("firebase-admin/app"); const {getStorage} = require("firebase-admin/storage"); const logger = require("firebase-functions/logger"); const path = require('path'); const {setGlobalOptions} = require("firebase-functions/v2"); const getRawBody = require('raw-body') var pdflibAddPlaceholder = require('@signpdf/placeholder-pdf-lib').pdflibAddPlaceholder; var signpdf = require('@signpdf/signpdf').default; var P12Signer = require('@signpdf/signer-p12').P12Signer; var { SUBFILTER_ETSI_CADES_DETACHED } = require('@signpdf/utils'); var PDFDocument = require('pdf-lib').PDFDocument; var { StandardFonts } = require('@pdf-lib/standard-fonts'); setGlobalOptions({region: "europe-west1"}); initializeApp(); exports.processPDF = onObjectFinalized({}, async (event) => { const bucket = admin.storage().bucket() const fileBucket = event.data.bucket; // Storage bucket containing the file. const filePath = event.data.name; // File path in the bucket. const contentType = event.data.contentType; // File content type. console.log(filePath); const certificatePath = "/certificate/client-identity.p12"; const file = bucket.file(filePath); const certificateFile = bucket.file(certificatePath); const fileDir = path.dirname(filePath); const fileBasename = path.basename(filePath); console.log(fileDir); if (fileDir != 'uploads') { return; } //Only continue if the file is uploaded into uploads folder getRawBody(file.createReadStream()) .then((pdfBuffer) => { console.log(pdfBuffer.length + ' bytes submitted'); getRawBody(certificateFile.createReadStream()) .then((certBuff) => { console.log(certBuff.length + 'bytes cert'); PDFDocument.load(pdfBuffer).then(function (pdfDoc) { console.log("loading pdf document"); console.log(pdfDoc); var signer = new P12Signer(certBuff, {passphrase: "123456"}); //This is the password's certificate pdflibAddPlaceholder({ pdfDoc: pdfDoc, reason: 'The user is declaring consent through JavaScript.', contactInfo: 'signpdf@example.com', name: 'John Doe', location: 'Free Text Str., Free World', }); pdfDoc.save().then(function (pdfWithPlaceholderBytes) { // And finally sign the document. signpdf .sign(pdfWithPlaceholderBytes, signer) .then(function (signedPdf) { console.log('Signed PDF'); }) }) }); }) .catch((err) => { console.log(err.message); }); }) .catch((err) => { console.log(err.message); }); });
错误信息
调用pdflibAddPlaceholder方法时触发如下错误:
TypeError: Cannot read properties of undefined (reading 'push') > at pdflibAddPlaceholder (/Users/Desktop/docSignLocal/node_modules/@signpdf/placeholder-pdf-lib/dist/pdflibAddPlaceholder.js:174:10) > at /Users/Desktop/docSignLocal/functions/index.js:51:25 > at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
问题原因
该错误源于@signpdf/placeholder-pdf-lib与当前使用的pdf-lib版本不兼容。pdf-lib v3+版本修改了PDF文档的内部属性结构,但@signpdf/placeholder-pdf-lib的现有实现依赖旧版本(v2.x)的结构,导致找不到需要执行push操作的数组。
解决方案
1. 降级pdf-lib到兼容版本
卸载当前pdf-lib,安装与@signpdf工具链兼容的v2.x版本(推荐2.17.1):
npm uninstall pdf-lib npm install pdf-lib@2.17.1
2. 重构代码为async/await写法(优化可读性与稳定性)
修改后的代码如下:
const {onObjectFinalized} = require("firebase-functions/v2/storage"); const admin = require('firebase-admin') const {initializeApp} = require("firebase-admin/app"); const path = require('path'); const {setGlobalOptions} = require("firebase-functions/v2"); const getRawBody = require('raw-body') const pdflibAddPlaceholder = require('@signpdf/placeholder-pdf-lib').pdflibAddPlaceholder; const signpdf = require('@signpdf/signpdf').default; const P12Signer = require('@signpdf/signer-p12').P12Signer; const PDFDocument = require('pdf-lib').PDFDocument; setGlobalOptions({region: "europe-west1"}); initializeApp(); exports.processPDF = onObjectFinalized({}, async (event) => { try { const bucket = admin.storage().bucket() const filePath = event.data.name; const fileDir = path.dirname(filePath); if (fileDir !== 'uploads') { console.log('Skipping non-uploads folder file'); return; } // 读取PDF文件和证书文件 const file = bucket.file(filePath); const pdfBuffer = await getRawBody(file.createReadStream()); console.log(`${pdfBuffer.length} bytes submitted`); const certificatePath = "/certificate/client-identity.p12"; const certificateFile = bucket.file(certificatePath); const certBuff = await getRawBody(certificateFile.createReadStream()); console.log(`${certBuff.length} bytes cert`); // 加载PDF文档 const pdfDoc = await PDFDocument.load(pdfBuffer); console.log("PDF document loaded"); // 初始化签名器 const signer = new P12Signer(certBuff, {passphrase: "123456"}); // 添加签名占位符 pdflibAddPlaceholder({ pdfDoc: pdfDoc, reason: 'The user is declaring consent through JavaScript.', contactInfo: 'signpdf@example.com', name: 'John Doe', location: 'Free Text Str., Free World', }); // 保存带占位符的PDF并签名 const pdfWithPlaceholderBytes = await pdfDoc.save(); const signedPdf = await signpdf.sign(pdfWithPlaceholderBytes, signer); console.log('Signed PDF generated successfully'); // 可选:将签名后的PDF保存回存储桶 const signedFilePath = `signed/${path.basename(filePath)}`; await bucket.file(signedFilePath).save(signedPdf); console.log(`Signed PDF saved to ${signedFilePath}`); } catch (err) { console.error('Processing failed:', err.message); } });
额外说明
- 确保P12证书路径正确,且Firebase Cloud Functions有权限读取该证书文件。
- 签名后的PDF可根据需求保存到指定存储路径(示例中保存至
signed文件夹)。
内容的提问来源于stack exchange,提问作者user3519266
相关产品推荐
相关产品推荐

