簡體   English   中英

使用iText將命名目標添加到現有PDF文檔

[英]Add named destinations to an existing PDF document with iText

我有一個以前使用FOP創建的PDF,我需要為其添加一些命名的目的地,以便以后另一個程序可以使用Adobe PDF打開參數(即#namedest = destination_name參數)打開和導航該文檔。

我不需要添加書簽或其他動態內容,而只需添加一些帶有名稱的目的地,從而注入一個/ Dests集合,並在生成的PDF中定義名稱。

我使用iText 5.3.0,並且閱讀了iText in Action(第二版)的第7章,但仍然無法弄清楚如何添加目標,因此在瀏覽器中將它們與#nameddest一起使用。

我正在使用PdfReader和PdfStamper閱讀和處理文檔。 我已經事先知道了在使用自定義的Listener和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();

我也嘗試過使用PdfFormField.createLink()創建一個PdfAnnotation,但是我仍然設法獲取注釋,但是沒有定義命名的目標,這是行不通的。

有什么解決辦法嗎? 我是否需要在現有的“塊”或其他內容上添加一些“鬼影”內容?

提前致謝。


編輯2016年1月27日 :我最近發現一個回答我的問題在iText的網站的示例部分, 在這里

不幸的是,如果我使用沒有預先定義目標的pdf測試它,那么提供的示例對我不起作用,因為原始Primes.pdf已經包含/ Dests數組。 此行為似乎與iText代碼一致,因為編寫者將目的地加載到PdfDocument的map屬性中,該屬性在關閉時未被壓模“繼承”。

就是說,我使用版本5.5.7中添加的PdfStamper的addNamedDestination()方法使它工作; 此方法將一個命名的目標加載到該類的本地地圖屬性中,稍后在關閉壓模時將其處理並合並到文檔中。

但是,這種方法引起了一個新問題:使用Pdf打開參數( #,#nameddest = )的導航在IE上可以正常運行,但在Chrome v47(可能還有Firefox)上不能正常運行。 我將問題追溯到在文檔中定義和引用目標名稱的順序。 壓模使用HashMap作為目的地的容器,這當然不能保證其對象的順序,並且無論出於什么原因,Chrome都無法識別未按“自然”順序列出的目的地。 因此,使它起作用的唯一方法是用自然排序的TreeMap替換namedDestinations HashMap。

希望這對其他人有幫助。

以前,我一直對我的項目有同樣的需求。 必須使用acrobat.jar查看器顯示和瀏覽pdf文檔。 要導航,我需要pdf中的命名目的地。 我已經在網上尋找了可能的解決方案,但對我來說並不幸運。 然后,我想到了這個主意。

我試圖用itext重新創建現有的pdf,瀏覽每頁並將本地目的地添加到每頁,然后我得到了想要的東西。 下面是我的代碼片段

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

以為會對您有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM