#java #pdfbox
#java #pdfbox
Вопрос:
Я работаю с PDFBOX v2, я пытаюсь клонировать первую PDPage PDDocument, чтобы сохранить ее в качестве шаблона для новых PDPages. На этой первой странице есть несколько полей acroform, которые мне нужно заполнить.
Я пробовал некоторые методы, но кто-то заставляет меня хотеть достичь.
1) Скопируйте содержимое первой страницы и добавьте его в документ, когда мне понадобится новая страница. Это копирует страницу, но поле acroform связано с другими полями страниц, и если я изменяю значение поля с первой страницы, это отображается на других страницах.
//Save in variable first page content
COSDictionary pageContent = (COSDictionary)doc.getPage(0).getCOSObject();
...
//when i need insert new page
doc.addPage(new PDPage(pageContent));
2) Клонируйте содержимое первой страницы, а затем добавьте в документ, как в первом методе. Это копирует страницу, но ни одно поле не копируется :/
PDFCloneUtility cloner = new PDFCloneUtility(doc);
COSDictionary pageContent = (COSDictionary)cloner.cloneForNewDocument(doc.getPage(0).getCOSObject());
...
//when i need insert new page
doc.addPage(new PDPage(pageContent));
Тогда, каков правильный способ сделать глубокую копию PDPage, получая поля acroform, независимые от первой страницы?
Спасибо!
Комментарии:
1. ИМХО, самым простым способом было бы удалить все страницы, кроме первой, а затем сохранить ее. Проблема в том, что Acroform — это уровень документа (поля) и уровень страницы (аннотации).
2. @TilmanHausherr есть какой-нибудь способ переименовать клонированные поля?
3. Вы вообще не должны использовать класс PDFCloneUtility, см. Его javadoc . Имя поля можно задать с
setPartialName()
помощью .4. @TilmanHausherr Я пробовал с аннотациями, и мне это не нравится, конечный пользователь pdf может его изменить :/
5. Извините, я не понимаю. Что вы пробовали и какой эффект не был желаемым?
Ответ №1:
Я получил решение!
1) Начните с пустого шаблона pdf, содержащего только 1 страницу. Откройте шаблон документа, заполните общие данные и сохраните как byte[] в памяти.
PDDocument templatedoc = PDDocument.load(new File(path));
PDDocumentCatalog catalog = templatedoc.getDocumentCatalog();
PDAcroFrom acroForm = catalog.getAcroForm());
... fill acroForm common data of all pages ...
ByteArrayOutputStream basicTemplate = new ByteArrayOutputStream();
templatedoc.save(basicTemplate);
byte[] filledBasicTemplate = basicTemplate.toByteArray();
2) Создайте новый документ для каждой необходимой страницы.
List<PDDocument> documents = new ArrayList<PDDocument>();
PDDocument activeDoc;
for(int i = 0; i < 5; i ) {
activeDoc = PDDocument.load(filledBasicTemplate);
documents.add(activeDoc);
... fill acroform or you need in each page ...
}
3) Импортируйте все первые страницы нового документа в окончательный документ и сохраните окончательный документ.
PDDocument finalDoc = new PDDocument();
for(PDDocument currentDoc : documents) {
... fill common things like page numbers ...
finalDoc.importPage(currentDoc.getPage(0));
}
finalDoc.save(new File(path));
... close all documents after save the final document ...
Возможно, это не самый оптимизированный код, но он работает.
Комментарии:
1. Это немного сбивает с толку; убедитесь, что виджеты, которые вы получаете при запуске из AcroForm, совпадают с вашими страницами, и что аннотации виджетов также указывают на страницу конечного документа. (вызов
annotation.setPage()
)