2013-11-19 6 views
4

Используя Apache PDFBox, я редактирую существующий документ, и я хотел бы взять одну страницу из этого документа и просто клонировать его, копируя все содержащиеся в нем элементы. Как дополнительный поворот, я хотел бы получить ссылку на все PDField s для любых полей формы на этой вновь клонированной странице. Вот код, который я пытался до сих пор:pdfbox: как клонировать страницу

  PDPage newPage = new PDPage(lastPage.getCOSDictionary()); 
      PDFCloneUtility cloner = new PDFCloneUtility(pdfDoc); 
      pdfDoc.addPage(newPage); 
      cloner.cloneMerge(lastPage, newPage); 

      // there doesn't seem to be an API to read the fields from the page, need to filter them out from the document. 
      List<PDField> newFields = readPdfFields(pdfDoc); 
      Iterator<PDField> i = newFields.iterator(); 
      while (i.hasNext()) { 
       if (i.next().getWidget().getPage() != newPage) 
        i.remove(); 
      } 

readPdfFields это вспомогательный метод, я написал, чтобы получить все поля документа с помощью AcroForm.

Но этот код, по-видимому, приводит к некоторому сбою/зависанию в моей JVM - я не смог отлаживать то, что происходит, но я предполагаю, что на самом деле это не правильный способ клонирования страницы. Что?

+0

Я не могу помочь вам клонировать страницу с PDFbox, но страница в формате pdf - это не то, что вы можете подумать. Например, acrofields не являются частью страницы. Acrofields находятся в каталоге (pdf root element) и указывают на страницы, где они должны появляться. Клонирование полей на новую страницу требует создания всех полей с новым именем и добавления их в массив acrofields со ссылкой на вашу новую страницу или, если поля должны быть одинаковыми полями, вам нужно добавить новую страницу к массиву страниц каждого поля. – thst

+0

@thth, я вижу. Кажется, я немного из глубины. Мои знания в PDF ограничены. Есть, по крайней мере, эти первые четыре строки, чтобы получить мне новую страницу с (неформатными) элементами старой страницы в них? – Dan

+0

Как я уже сказал, я не могу помочь вам с использованием PDFBox. Но stackoverflow может помочь: Посмотрите на этот вопрос [клонирование страницы]. Загружается PDF-файл, и его страницы импортируются в один и тот же pdf-файл. Но это также должно работать и на ваш сценарий. Извините за то, что вы не стали более полезными! – thst

ответ

9

Наименее ресурсоемкий способ клонировать страницу неполной копия соответствующего словаря:

PDDocument doc = PDDocument.load(file); 

List<PDPage> allPages = doc.getDocumentCatalog().getAllPages(); 

PDPage page = allPages.get(0); 
COSDictionary pageDict = page.getCOSDictionary(); 
COSDictionary newPageDict = new COSDictionary(pageDict); 

newPageDict.removeItem(COSName.ANNOTS); 

PDPage newPage = new PDPage(newPageDict); 
doc.addPage(newPage); 

doc.save(outfile); 

я явно удалил аннотации (поля формы и т.д.) из копии, потому что аннотация имеет ссылку, указывающую назад на его страницу, которая на скопированной странице явно неверна.

Таким образом, если вы хотите, чтобы аннотации проходили в чистом виде, вам необходимо создать мелкие копии массива аннотаций и все содержащиеся в нем словари аннотаций, а также заменить ссылку на страницу в ней.

Большинство читателей в формате PDF не будут возражать, если ссылки на страницы неверны. Поэтому для грязного решения вы можете просто оставить аннотации в словаре страниц. Но кто хочет быть грязным ...;)

Если вы хотите дополнительно изменить некоторые части новой или старой страницы, вам, очевидно, также придется скопировать соответствующие объекты PDF, прежде чем манипулировать ими.

Некоторые другие замечания:

Исходная страница Клонирование мне выглядит странно. В конце концов вы снова добавляете идентичный словарь страниц в документ (повторяющиеся записи в дереве страниц игнорируются, я думаю), а затем некоторые слияния между этими идентичными объектами страницы.

Я предполагаю, что PDFCloneUtility предназначен для клонирования между различными документами, а не внутри одного и того же, но слияние словаря в себя не нужно работать.

Я хотел бы получить ссылку на всю PDFields для любой полой формы в этой новом клонированной странице

Поскольку поля имеют одинаковые имена, они идентичны!

Поля в формате PDF - это абстрактные поля, которые могут иметь много видимых надписей. Одно и то же имя подразумевает одно и то же поле.

Поле, отображаемое на некоторой странице, означает, что на странице есть аннотация, представляющая это поле. Чтобы усложнить ситуацию, словарь словарей и словарь можно объединить для полей только с одним видом.

Таким образом, в зависимости от ваших требований вам сначала нужно будет решить, хотите ли вы работать с полями или с аннотациями полей.

+0

Я по-прежнему работаю над этой проблемой. Этот ответ заставил меня начать по правильному пути, но теперь у меня есть вопрос. Учитывая PDPage и его аннотации, есть ли способ, предполагающий, что данная аннотация связана с PDField, чтобы фактически получить этот объект PDField? – Dan

+0

По существу, вы должны проверить, относится ли объект аннотации к одному и тому же объекту PDF ('COSDictionary') в качестве объекта PDF поля или любого из его детей. Однако, посмотрев на код PDFBox, становится очевидным, что библиотека предполагает, что поля находятся в одном упорядоченном списке, в то время как они фактически могут быть организованы в древовидной структуре с унаследованными атрибутами и т. Д. Поэтому я в настоящее время (PDFBox 2.0.0- SNAPSHOT) не может советовать, используя это для произвольных PDF-файлов, только для PDF-файлов, которые, как вы знаете, имеют свои поля в виде плоского списка. – mkl

+0

Спасибо. когда вы говорите «тот же объект PDF», означает ли это, что тест '.equals()' на двух объектах COSDictionary' возвращал true или это нечто более тонкое? – Dan

Смежные вопросы