2015-04-26 5 views
0

У меня есть PDF, ранее созданный с помощью FOP, и мне нужно добавить некоторые именованные адресаты, чтобы позже другая программа могла открывать и перемещать документ с открытыми параметрами Adobe PDF, а именно параметр # namedest = destination_name.Добавьте именованные адресаты в существующий PDF-документ с iText

Мне не нужно добавлять закладки или другой динамический контент, но только некоторые адресаты с именем и, таким образом, вводят коллекцию/Dests с именами, определенными в полученном PDF-файле.

Я использую IText 5.3.0 и я прочитал главу 7 IText в действии (второе издание), но до сих пор я не могу понять, как добавить адресатов и поэтому использовать их с #nameddest в браузере.

Я читаю документ и обрабатываю его с помощью PdfReader и PdfStamper. Я уже заранее знаю, куда поместить каждый пункт назначения после анализа документа с помощью настраиваемого прослушивателя и PdfContentStreamProcessor, для поиска определенного текстового маркера на каждой странице.

Это сокращенный вариант моего кода:

PdfReader reader = new PdfReader(src); 
PdfStamper stamper = new PdfStamper(reader, new BufferedOutputStream(dest)); 

// search text markers for destinations, page by page 
for (int i=1; i<reader.getNumberOfPages(); i++) { 
    // get a list of markers for this page, as obtained with a custom Listener and a PdfContentStreamProcessor 
    List<MyDestMarker> markers = ((MyListener)listener).getMarkersForThisPage(); 

    // add a destination for every text marker in the current page 
    Iterator<MyDestMarker> it = markers.iterator(); 
    while(it.hasNext()) { 
    MyDestMarker marker = it.next(); 
    String name = marker.getName(); 
    String x = marker.getX(); 
    String y = marker.getY(); 

    // create a new destination 
    PdfDestination dest = new PdfDestination(PdfDestination.FITH, y); // or XYZ 

    // add as a named destination -> does not work, only for new documents? 
    stamper.getWriter().addNamedDestination(name, i /* current page */, dest); 

    // alternatives 
    PdfContentByte content = stamper.getOverContent(i); 
    content.localDestination(name, dest); // doesn't work either -> no named dest found 

    // add dest name to a list for later use with Pdf Open Parameters 
    destinations.add(name); 
    } 
} 

stamper.close(); 
reader.close(); 

Я также попытался создать PdfAnnotation с PdfFormField.createLink(), но до сих пор, я просто управлять, чтобы получить аннотацию, но без названного пункта назначения определено, что делает не работа.

Любое решение для этого? Нужно ли добавлять какой-то «призрачный» контент поверх существующего с кусками или что-то еще?

Заранее спасибо.


редактировать 01-27-2016: Недавно я нашел ответ на свой вопрос в разделе примеров сайта IText, here.

К сожалению, пример, приведенный не работает для меня, если я проверить это с PDF без назначения ранее определенного в нем, как и в случае с источником primes.pdf который уже содержит /Dests массива. Такое поведение, по-видимому, согласуется с кодом iText, так как автор загружает адресаты в атрибут карты PdfDocument, который не «унаследован» штампом при закрытии.

При этом я получил его, используя метод addNamedDestination() из PdfStamper с версией 5.5.7; этот метод загружает именованный пункт назначения в атрибут локальной карты класса, который впоследствии обрабатывается и консолидируется в документе при закрытии штампа.

Этот подход рассмотрел новую проблему: навигацию с открытыми параметрами Pdf (#, # nameddest =) отлично работает с IE, но не с Chrome v47 (и, вероятно, с Firefox тоже). Я отследил проблему до порядка, в котором имена dests определены и указаны внутри документа; то шаблон использует HashMap в качестве контейнера для пунктов назначения, что, конечно же, не гарантирует порядок его объектов и по какой-либо причине Chrome отказывается распознавать адресатов, не указанных в «натуральном» порядке. Таким образом, единственный способ, которым я получил его, - заменить namedDestinations HashMap с помощью упорядоченного дерева TreeMap.

Надеюсь, что это поможет другим людям с тем же вопросом.

+0

Я только что посмотрел это, и нет простого способа сделать то, что вы хотите. Вероятно, это то, что потребует дополнительной разработки ядра в iText. –

+0

Спасибо Бруно, к сожалению, я думал, что есть способ сделать это с помощью шаблона ... Как вы думаете, есть ли способ создать схему с закладками и, возможно, «спрятать» их? Кстати, спасибо за вашу работу с iText, которую я считаю очень полезной. – gioefex

+0

Пока не знаю. У меня нет времени прямо сейчас, но я «одобрил» вопрос, чтобы не забыть об этом после моей командировки (я постоянно путешествую). –

ответ

0

Я раньше был в моем проекте. Приходилось отображать и перемещать документ pdf с помощью программы просмотра acrobat.jar. Для навигации мне нужны названные адресаты в pdf. Я просмотрел веб-сайт для возможного решения, но мне не повезло. Тогда я эту мысль бросаю в голову.

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

OutputStream outputStream = new FileOutputStream(new File(filename)); 
Document document = new Document(); 
PdfWriter writer = PdfWriter.getInstance(document, outputStream); 
document.open(); 
PdfContentByte cb = writer.getDirectContent(); 
PdfOutline pol = cb.getRootOutline(); 
PdfOutline oline1 = null; 
InputStream in1 = new FileInputStream(new File(inf1)); 
PdfReader reader = new PdfReader(in1); 
for (int i = 1; i <= reader.getNumberOfPages(); i++) 
{ 
    document.newPage(); 
    document.setMargins(0.0F, 18.0F, 18.0F, 18.0F); 
    PdfImportedPage page = writer.getImportedPage(reader, i); 
    document.add(new Chunk(new Integer(i).toString()).setLocalDestination(new Integer(i).toString())); 
    System.out.println(i); 
    cb.addTemplate(page, 0.0F, 0.0F); 
} 
outputStream.flush(); 
document.close(); 
outputStream.close(); 

Думал, что это вам поможет.

+0

Спасибо, интересное решение. Btw Я не думаю, что могу использовать Chunk с document.add(), потому что мне нужно место назначения в определенной позиции внутри страницы ... может быть, прямоугольник и класс DrawInterface, но я должен попробовать ... – gioefex

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