Каков правильный способ глубокого клонирования PDPage?

#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() )