You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用@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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 10:02:40