Reputation: 33
I have a digital sign pdf with 2 form field having the same name. when i try fill up the field using PDFBOX and open it in Acrobat the field content is empty. It only will show the content when i click on the field.
This my code
File inFile= new File("pdfFile/Untitled_sign.pdf");
OutputStream outFile = new FileOutputStream("pdfFile/Untitled_sign_2.pdf");
PDDocument pdfDocument = PDDocument.load(inFile);
PDAcroForm acroForm = pdfDocument.getDocumentCatalog().getAcroForm();
Set<COSDictionary> cosDis= new HashSet<>();
if (acroForm != null) {
List<PDField> fields = acroForm.getFields();
//acroForm.setNeedAppearances(true);
for (PDField field : fields) {
if(field instanceof PDTextField) {
System.out.println(field.getFullyQualifiedName());
if(field.getFullyQualifiedName().equals("Text1")) {
try {
field.setValue("100");
System.out.println("New value: " + field.getValueAsString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
field.getCOSObject().setNeedToBeUpdated(true);
cosDis.add(field.getCOSObject());
}
}
}
acroForm.getCOSObject().setNeedToBeUpdated(true);
cosDis.add(acroForm.getCOSObject());
}
pdfDocument.saveIncremental(outFile,cosDis);
here the pdf https://drive.google.com/file/d/1SeGiPhoEqtkuKGHT3FG063d9lbtFrnt0/view?usp=sharing
and here the result https://drive.google.com/file/d/1LHxDuHIztRv-r27pYTmRYIwUEkdaX_75/view?usp=sharing
[EDIT]
after Tilman recommended using field.getWidgets().get(0).getAppearance().getCOSObject().setNeedToBeUpdated(true); it able to display correctly. But when i do digital sign again, the content will go back to original content. For example, I fill in the pdf with "test" and digital sign the pdf. (original pdf https://drive.google.com/file/d/1SoVgWMfRVbVsWVOSRRFU7bjyJARHFmZV/view?usp=sharing)
(first digital sign pdf https://drive.google.com/file/d/1sbklXp8s1R9OoH3xwJPZ54o0TUV_bl4m/view?usp=sharing)
after digital sign i used pdfbox to change the content from "test" to "100". it able to display "100" correctly in acrobat. (pdf with "100" https://drive.google.com/file/d/13ViNcGJ7g0d6Kcxn8MsGQKF9DMFCD-1a/view?usp=sharing)
but if i digital sign again it will change back to "test" (second digital sign https://drive.google.com/file/d/1uiv4UddZHnMBNzNE7LlIg7Gb1bzUVLlM/view?usp=sharing) This the new code i added but is this the same. when it digital sign the content will chnage back to "test"
PDDocument pdfDocument = PDDocument.load(inFile);
PDAcroForm acroForm = pdfDocument.getDocumentCatalog().getAcroForm();
Set<COSDictionary> cosDis= new HashSet<>();
if (acroForm != null) {
List<PDField> fields = acroForm.getFields();
for (PDField field : fields) {
if(field instanceof PDTextField) {
if(field.getFullyQualifiedName().equals("Text1")) {
try {
field.setValue("200");
System.out.println("New value: " + field.getValueAsString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
field.getCOSObject().setNeedToBeUpdated(true);
for(PDAnnotationWidget wed: field.getWidgets()) {
wed.getAppearance().getCOSObject().setNeedToBeUpdated(true);
wed.getCOSObject().setNeedToBeUpdated(true);
}
COSDictionary fieldDictionary = field.getCOSObject();
COSDictionary dictionary = (COSDictionary) fieldDictionary.getDictionaryObject(COSName.AP);
if(dictionary!=null) {
dictionary.setNeedToBeUpdated(true);
COSStream stream = (COSStream) dictionary.getDictionaryObject(COSName.N);
stream.setNeedToBeUpdated(true);
}
while (fieldDictionary != null)
{
fieldDictionary.setNeedToBeUpdated(true);
fieldDictionary = (COSDictionary) fieldDictionary.getDictionaryObject(COSName.PARENT);
}
}
}
}
acroForm.setSignaturesExist(true);
acroForm.setAppendOnly(true);
acroForm.getCOSObject().setDirect(true);
acroForm.getCOSObject().setNeedToBeUpdated(true);
//acroForm.setNeedAppearances(true);
COSObject pdfFields = acroForm.getCOSObject().getCOSObject(COSName.FIELDS);
if (pdfFields != null) {
pdfFields.setNeedToBeUpdated(true);
}
pdfDocument.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);
cosDis.add(pdfDocument.getDocumentCatalog().getCOSObject());
cosDis.add(acroForm.getCOSObject());
}
pdfDocument.saveIncremental(outFile,cosDis);
Upvotes: 0
Views: 222
Reputation: 33
Thank you Tilman Hausherr. the solution i found is by setNeedToBeUpdated() in the COSName.AP and COSName.N inside the COSName.KIDS.
here my final code.
PDDocument pdfDocument = PDDocument.load(inFile);
PDAcroForm acroForm = pdfDocument.getDocumentCatalog().getAcroForm();
Set<COSDictionary> cosDis= new HashSet<>();
if (acroForm != null) {
List<PDField> fields = acroForm.getFields();
for (PDField field : fields) {
if(field instanceof PDTextField) {
if(field.getFullyQualifiedName().equals("Text1")) {
try {
field.setValue("200");
System.out.println("New value: " + field.getValueAsString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
field.getCOSObject().setNeedToBeUpdated(true);
cosDis.add(field.getCOSObject());
for(PDAnnotationWidget wed: field.getWidgets()) {
wed.getAppearance().getCOSObject().setNeedToBeUpdated(true);
wed.getCOSObject().setNeedToBeUpdated(true);
cosDis.add(wed.getAppearance().getCOSObject());
cosDis.add(wed.getCOSObject());
}
COSDictionary fieldDictionary = field.getCOSObject();
COSDictionary dictionary = (COSDictionary) fieldDictionary.getDictionaryObject(COSName.AP);
if(dictionary!=null) {
dictionary.setNeedToBeUpdated(true);
cosDis.add(dictionary);
COSStream stream = (COSStream) dictionary.getDictionaryObject(COSName.N);
stream.setNeedToBeUpdated(true);
cosDis.add(stream);
}else {
COSArray dictionary2 = (COSArray) fieldDictionary.getDictionaryObject(COSName.KIDS);
for (int i = 0; i < dictionary2.size(); i++)
{
COSDictionary kidAp=(COSDictionary) ((COSDictionary)dictionary2.getObject(i)).getDictionaryObject(COSName.AP);
if(kidAp!=null) {
kidAp.setNeedToBeUpdated(true);
cosDis.add(kidAp);
COSStream kidApstream = (COSStream) kidAp.getDictionaryObject(COSName.N);
kidApstream.setNeedToBeUpdated(true);
cosDis.add(kidApstream);
}
}
}
while (fieldDictionary != null)
{
fieldDictionary.setNeedToBeUpdated(true);
cosDis.add(fieldDictionary);
fieldDictionary = (COSDictionary) fieldDictionary.getDictionaryObject(COSName.PARENT);
}
}
}
}
acroForm.setSignaturesExist(true);
acroForm.setAppendOnly(true);
acroForm.getCOSObject().setDirect(true);
acroForm.getCOSObject().setNeedToBeUpdated(true);
//acroForm.setNeedAppearances(true);
COSObject pdfFields = acroForm.getCOSObject().getCOSObject(COSName.FIELDS);
if (pdfFields != null) {
pdfFields.setNeedToBeUpdated(true);
}
pdfDocument.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);
cosDis.add(pdfDocument.getDocumentCatalog().getCOSObject());
cosDis.add(acroForm.getCOSObject());
}
pdfDocument.saveIncremental(outFile,cosDis);
Hope this help. ;)
Upvotes: 0