Search code examples
javapdfbox

Issue with PDFBox 2.0.28 when using CreateVisibleSignature to add visible signature after using document.saveIncremental


I have a Java application using PDFBox 2.0.28, and I'm facing a problem when trying to add a signature to a PDF document. The process involves preparing empty fields in the document, populating these fields, and finally adding a signature using the CreateVisibleSignature code example.

Here's a simplified overview of the relevant code:

  // Write the content byte[] to the hard disk
  _filesManipulator.writeFil(
    documentToSigne.Content,
    baseNameFiles + FilesManipilator.ORIGINAL_PDF);

  // Test if the file contains a signature
  boolean isConatinSignature = _pdfManipulator.isDocumentContainsSignature(content);
  if (!isConatinSignature) {
    // Add empty fields to the PDF document and save it to the hard disk
    _pdfManipulator.PrepaireEmptyFieldsToDocument(baseNameFiles + FilesManipilator.ORIGINAL_PDF,
        baseNameFiles + FilesManipilator.ORIGINAL_PDF, documentToSigne, event.CurrentMemberInfo);
 }

  // Populate the fields and save the incremental file to the hard disk
  _pdfManipulator.populateFieldsInDocument(baseNameFiles + FilesManipilator.ORIGINAL_PDF,
    baseNameFiles + FilesManipilator.ORIGINAL_PDF,
    event.CurrentMemberInfo.Configs);

  // Add a signature using the `CreateVisibleSignature` example
  _pdfManipulator.addSignatureFormConfigs(baseNameFiles, event, event.CurrentMemberInfo,    documentToSigne);
  
 // ------------------------------------------------------------------


 //and this is the code of 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);
        }
        // get liste of configFilds to prepar the list of filds to add 
 in a document
        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();
    }
  // ------------------------------------------------------------------


  //and this is the code of populateFieldsInDocument

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

        PDDocument document = PDDocument.load(new File(pathSource));
        // Get the AcroForm from the document
        PDAcroForm acroForm = 
 document.getDocumentCatalog().getAcroForm();

        // Loop through the configList and populate fields
        for (DocumentMemberConfigDto config : configList) {

            PDField field = acroForm.getField(config.id);
            if (field != null && 
 !config.fieldLibelle.equals("Signature")) {

                   // set the value of fild
                }
            }
        }
        
 document.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);
 document.getDocumentCatalog().getAcroForm().getCOSObject().setNeedToBeUpdated(true);
        FileOutputStream fileOutputStream = new FileOutputStream(new 
  File(pathdestination));
        document.saveIncremental(fileOutputStream);
        document.close();
    }

The issue arises when calling document.saveIncremental(fileOutputStream); in the populateFieldsInDocument method. This causes the second step to add a signature to fail, with the error message: "Error: Header doesn't contain versioninfo."

I suspect that the problem might be related to the use of document.saveIncremental, but I'm not entirely sure how to resolve it. Any insights or suggestions on how to fix this issue would be greatly appreciated.

Thank you in advance!

: 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.(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]


Solution

  • You use the same file for reading and writing:

      // Populate the fields and save the incremental file to the hard disk
      _pdfManipulator.populateFieldsInDocument(baseNameFiles + FilesManipilator.ORIGINAL_PDF,
        baseNameFiles + FilesManipilator.ORIGINAL_PDF,
        event.CurrentMemberInfo.Configs);
    

    While this works fine for regular saves, incremental saves need the original file to copy from.

    Thus, use different source and destination files, at least for incremental saves.