Значения полей формы, установленные с помощью 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);