Значения полей формы, установленные с помощью PDFBOX, не отображаются в Adobe Reader

У меня возникла проблема с попыткой установить некоторые из полей с помощью Apache PDFBOX (1.8.5). У меня есть несколько разных статических PDF файлов, которые я использую для тестирования. Используя следующий код, я могу установить значения полей формы и сохранить полученный PDF. Затем я могу открыть этот PDF-документ в Adobe Reader и посмотреть результаты:

PDDocumentCatalog docCatalog = pdfDocument.getDocumentCatalog();
pdfTemplate.setAllSecurityToBeRemoved(true);
PDAcroForm acroForm = docCatalog.getAcroForm();
List fields = acroForm.getFields();     
Iterator fieldsIter = fields.iterator();        
while( fieldsIter.hasNext())
{
    PDField field = (PDField)fieldsIter.next();         
    if(field instanceof PDTextbox){
        ((PDTextbox)field).setValue("STATIC PDFBOX EDIT");
    }
}

И затем я в конечном итоге сохраняю форму. Для статических PDF файлов:

  • Версия PDF: 1.6 (Acrobat 7.x)
  • Версия PDF: 1.7 (Acrobat 8.x)

Это работает отлично. Я могу открыть Документы в Adobe Reader XI и увидеть правильные значения в форме.

Для статических PDF файлов:

  • Версия PDF: 1.7 Уровень расширения Adobe 3 (Acrobat 9.x)
  • Версия PDF: 1.7 Уровень расширения Adobe 8 (Acrobat X)
  • Версия PDF: 1.7 Уровень расширения Adobe 11 (Acrobat XI)

Кажется, что это не работает. Когда я открываю полученные формы в Adobe Reader XI, поля, похоже, не заполняются. Но если я открою PDF файл в браузере Firefox Firefox или браузера Chrome, поля будут отображаться как заполненные там.

Как установить эти поля, чтобы значения отображались при просмотре в Adobe Reader XI?

EDIT: Примеры PDF файлов можно найти здесь: https://github.com/bamundson/PDFExample

Ответ 1

Основное различие между вашими PDF файлами - используемая технология формы:

  • Test_9.pdf использует хорошие ol'fashioned формы AcroForm;
  • Test_10.pdf и Test_10.pdf, с другой стороны, используйте гибридную форму с представлением AcroForm и представлением XFA (Adobe XML Forms Architecture).

XFA-осведомленные читатели PDF (то есть, прежде всего Adobe Reader и Adobe Acrobat) используют XFA информацию из файла, в то время как XFA-не подозревающие зрители (то есть большинство других) используют AcroForm информация.

PDFBox в основном XFA-не знает. Это означает, что объекты PDField, возвращаемые PDAcroForm.getFields(), представляют только информацию AcroForm. Таким образом, ваши вызовы ((PDTextbox)field).setValue("STATIC PDFBOX EDIT") влияют только на представление AcroForm формы.

Это объясняет ваше наблюдение

Когда я открываю полученные формы в Adobe Reader XI, поля, похоже, не заполняются. Но если я открою PDF файл в браузере Firefox Firefox или браузера Chrome, поля будут отображаться как заполненные там.

(Насколько я знаю, Firefox и Chrome, интегрированные в PDF-тестеры, XFA-не знают.)

Итак,

Как установить эти поля, чтобы значения отображались при просмотре в Adobe Reader XI?

Существуют два способа:

  • Удалите запись XFA из словаря AcroForm:

    acroForm.setXFA(null);
    

    Если нет XFA, Adobe Reader также будет использовать информацию формы AcroForm.

  • Отредактируйте информацию AcroForm и XFA. Вы можете получить информацию XFA, используя

    PDXFAResource xr = acroForm.getXFA();
    

    и извлеките базовый XML, используя

    xr.getDocument()
    

    Затем вы можете редактировать XML, поместить полученный XML в поток, который вы можете обернуть в PDXFAResource, который затем вы можете установить с помощью AcroForm.setXFA(...).

Хотя вариант 1, безусловно, намного проще реализовать, он работает только для гибридных документов. Если вам также придется редактировать чистые формы XFA, вам нужно реализовать вариант 2.

Запись новых значений полей в эти PDF файлы отлично работает с последней версией iText

iText имеет определенную степень явной поддержки форм XFA.

Ответ 2

Вам нужно установить флаг NeedAppearances в true для acrofields. Попробуйте выполнить фрагмент кода. Он правильно отобразит значения в полях.

COSDictionary acroFormDict = new COSDictionary(); 
acroFormDict.setBoolean(COSName.getPDFName("NeedAppearances"), true);
acroFormDict.setItem(COSName.getPDFName("Fields"), new COSArray());

// add a new AcroForm and add that to the document
PDAcroForm acroForm = new PDAcroForm(document, acroFormDict);