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

PDFBox 2.0.28增量保存后添加可见签名报Header无版本信息错误

PDFBox 2.0.28 签名流程中saveIncremental导致的"Header doesn't contain versioninfo"问题

问题背景

我开发了一个基于PDFBox 2.0.28的Java应用,在给PDF添加签名时遇到异常。流程为:先在文档中创建空表单字段,填充字段内容,最后通过CreateVisibleSignature示例代码添加可见签名。

相关代码片段

主流程代码

// 将内容字节数组写入磁盘
_filesManipulator.writeFil(
  documentToSigne.Content,
  baseNameFiles + FilesManipilator.ORIGINAL_PDF);

// 检测文档是否包含签名
boolean isConatinSignature = _pdfManipulator.isDocumentContainsSignature(content);
if (!isConatinSignature) {
  // 给PDF添加空字段并保存到磁盘
  _pdfManipulator.PrepaireEmptyFieldsToDocument(baseNameFiles + FilesManipilator.ORIGINAL_PDF,
      baseNameFiles + FilesManipilator.ORIGINAL_PDF, documentToSigne, event.CurrentMemberInfo);
}

// 填充字段并增量保存到磁盘
_pdfManipulator.populateFieldsInDocument(baseNameFiles + FilesManipilator.ORIGINAL_PDF,
  baseNameFiles + FilesManipilator.ORIGINAL_PDF,
  event.CurrentMemberInfo.Configs);

// 使用CreateVisibleSignature示例添加签名
_pdfManipulator.addSignatureFormConfigs(baseNameFiles, event, event.CurrentMemberInfo, documentToSigne);

PrepaireEmptyFieldsToDocument方法

public void PrepaireEmptyFieldsToDocument(String pathSource, String pathdestination,
                                          DocumentToSignDto documentToSigne, MemberSignerConfigsDto CurrentMemberInfo) throws IOException {
    PDDocument document = PDDocument.load(new File(pathSource));

    PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
    if (acroForm == null) {
        acroForm = new PDAcroForm(document);
        document.getDocumentCatalog().setAcroForm(acroForm);
    }
    // 获取需要添加的字段配置列表
    List<DocumentMemberConfigDto> LastConfigList = documentToSigne.MemberSignerConfigs.stream()
            .flatMap(doc -> doc.Configs.stream())
            .collect(Collectors.toList());

    creatFilds(document, acroForm, LastConfigList);

    List<DocumentMemberConfigDto> CurrentConfigList = CurrentMemberInfo.Configs.stream()
            .filter(p -> p.docOrder == documentToSigne.Order)
            .collect(Collectors.toList());

    creatFilds(document, acroForm, CurrentConfigList);

    document.save(pathdestination);
    document.close();
}

populateFieldsInDocument方法

public void populateFieldsInDocument(String pathSource, String pathdestination,
                                    java.util.List<DocumentMemberConfigDto> configList)
        throws IOException {

    PDDocument document = PDDocument.load(new File(pathSource));
    // 获取文档的AcroForm
    PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();

    // 遍历配置列表填充字段
    for (DocumentMemberConfigDto config : configList) {
        PDField field = acroForm.getField(config.id);
        if (field != null && !config.fieldLibelle.equals("Signature")) {
               // 设置字段值
        }
    }
    
    document.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);
    document.getDocumentCatalog().getAcroForm().getCOSObject().setNeedToBeUpdated(true);
    FileOutputStream fileOutputStream = new FileOutputStream(new File(pathdestination));
    document.saveIncremental(fileOutputStream);
    document.close();
}

问题现象

调用populateFieldsInDocument方法中的document.saveIncremental(fileOutputStream)后,后续签名步骤失败,报错信息如下:

message : [B@4d8a41c1Error while processing the message: Error: Header doesn't contain versioninfo
java.io.IOException: Error: Header doesn't contain versioninfo
at org.apache.pdfbox.pdfparser.PDFParser.parse(PDFParser.java:221) ~[pdfbox-2.0.28.jar!/:2.0.28]
at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:1110) ~[pdfbox-2.0.28.jar!/:2.0.28]
at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:1093) ~[pdfbox-2.0.28.jar!/:2.0.28]
at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:1052) ~[pdfbox-2.0.28.jar!/:2.0.28]
at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:1000) ~[pdfbox-2.0.28.jar!/:2.0.28]
at org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSignDesigner.calculatePageSizeFromFile(PDVisibleSignDesigner.java:171) ~[pdfbox-2.0.28.jar!/:2.0.28]
at org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSignDesigner.<init>(PDVisibleSignDesigner.java:72) ~[pdfbox-2.0.28.jar!/:2.0.28]
at co.netcom.signature.CreateVisibleSignature.setVisibleSignDesigner(CreateVisibleSignature.java:73) ~[classes!/:0.0.1-SNAPSHOT]

解决思路与建议

  1. 根本原因:saveIncremental是增量更新PDF,会在原文件末尾追加更新内容,但你当前代码中源文件和目标文件路径完全相同,导致原文件被覆盖破坏,后续加载时PDFParser无法识别有效PDF头部信息。

  2. 修复方案:

    • 增量更新时,源文件和目标文件必须使用不同路径,先写入临时文件,完成后再替换原文件。
    • 修改populateFieldsInDocument方法的输出逻辑:
      public void populateFieldsInDocument(String pathSource, String pathdestination,
                                         java.util.List<DocumentMemberConfigDto> configList)
              throws IOException {
      
          PDDocument document = PDDocument.load(new File(pathSource));
          PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
      
          for (DocumentMemberConfigDto config : configList) {
              PDField field = acroForm.getField(config.id);
              if (field != null && !config.fieldLibelle.equals("Signature")) {
                     // 设置字段值
              }
          }
          
          document.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);
          document.getDocumentCatalog().getAcroForm().getCOSObject().setNeedToBeUpdated(true);
          
          // 使用临时文件存储增量更新内容
          String tempFilePath = pathdestination + ".tmp";
          FileOutputStream fileOutputStream = new FileOutputStream(new File(tempFilePath));
          document.saveIncremental(fileOutputStream);
          document.close();
          fileOutputStream.close();
          
          // 替换原文件
          Files.move(Paths.get(tempFilePath), Paths.get(pathdestination), StandardCopyOption.REPLACE_EXISTING);
      }
      
  3. 额外优化:检查PrepaireEmptyFieldsToDocument中的document.save(pathdestination),如果同样存在源路径和目标路径相同的情况,建议也采用临时文件替换的方式,避免潜在的文件损坏风险。

内容的提问来源于stack exchange,提问作者rahim soufiane

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 10:04:57