foliojs / pdfkit

A JavaScript PDF generation library for Node and the browser
http://pdfkit.org/
MIT License
9.8k stars 1.14k forks source link

Error in finalizing AcroForm #1118

Closed erickximenes closed 4 years ago

erickximenes commented 4 years ago

My code:

const signpdf = require('node-signpdf');
const PDFDocument = require('pdfkit');
const fs = require('fs');

doc = new PDFDocument({
    autoFirstPage: true,
    size: 'A4',
    margins: { top: 90, bottom: 80, left: 72, right: 72 },
    layout: 'portrait',
    bufferPages: true,
});

let fieldIds = [],
    form;
const signatureLength = 8192,
    byteRangePlaceholder = '**********',
    signature = doc.ref({
        Type: 'Sig',
        Filter: 'Adobe.PPKLite',
        SubFilter: 'adbe.pkcs7.detached',
        ByteRange: [
            0,
            byteRangePlaceholder,
            byteRangePlaceholder,
            byteRangePlaceholder
        ],
        Contents: Buffer.from(String.fromCharCode(0).repeat(signatureLength)),
        Reason: new String("Blabla"),
        M: new Date(),
        ContactInfo: new String("bla@bla.pt"),
        Name: new String('Bla'),
        Location: new String('Bla')
    }),
    signatureName = 'Signature',
    widget = doc.ref({
        Type: 'Annot',
        Subtype: 'Widget',
        FT: 'Sig',
        Rect: [0, 0, 0, 0],
        V: signature,
        T: new String(signatureName + (fieldIds.length + 1)),
        F: 4,
        P: doc.page.dictionary
    });
doc.page.dictionary.data.Annots = [widget];

form = doc.ref({
    Type: 'AcroForm',
    SigFlags: 3,
    Fields: [...fieldIds, widget]
});
doc._root.data.AcroForm = form;
signature.end();
widget.end();
form.end();
doc.end();

const pdf = fs.readFileSync("este.pdf");
const cert = fs.readFileSync("teste.p12");

const assinarPDF = new signpdf.SignPdf(
    pdf,
    cert, { passphrase: '123' }
);

Erro

C:\Users\erick\node_modules\pdfkit\js\pdfkit.js:4900 if (!Object.keys(this._acroform.fonts).length && !this._acroform.defaultFont) { ^

TypeError: Cannot read property 'fonts' of undefined at PDFDocument.endAcroForm (C:\Users\erick\node_modules\pdfkit\js\pdfkit.js:4900:39) at PDFDocument.end (C:\Users\erick\node_modules\pdfkit\js\pdfkit.js:5506:10) at Object. (C:\Users\erick\Documents\teste\index.js:79:5) at Module._compile (internal/modules/cjs/loader.js:1138:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10) at Module.load (internal/modules/cjs/loader.js:986:32) at Function.Module._load (internal/modules/cjs/loader.js:879:14) at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12) at internal/main/run_main_module.js:17:47 P

eminoda commented 2 years ago

我也遇到这样的情况,我的 node-signpdf 版本是这个:1.5.0,不过后面定位是 pdfkit 的升级导致 node-signpdf 不可用。

参考:https://github.com/vbuch/node-signpdf/issues/88

在 pdfkit 添加了一些方法,比如:initForm,导致 node-signpdf 中的 pdfkitAddPlaceholder 不能正常工作!

你可以单独做一个 pdfkitAddPlaceholder 方法,把一些异常错误做个处理:

// ...
const pdf = new PDFDocument({
      autoFirstPage: false,
      size: 'A4',
      layout: 'portrait',
      bufferPages: true,
    })
    pdf.initForm() // 注意!!!
    pdf
      .addPage()
      .fillColor('#333')
      .fontSize(25)
      .text('Hello PdfDocument ' + Date.now())
      .save()
// ...
// your pdfkitAddPlaceholder.js
// ...
let form;

if (!isAcroFormExists) {
  // Create a form (with the widget) and link in the _root
  form = pdf.ref({
    Type: 'AcroForm',
    SigFlags: 3,
    Fields: [...fieldIds, widget],
    // 注意!!!
    DR: {
      Font: {}
    }
  });
} else {
// ...