2014-05-05 44 views
0

生成PDF時我有一個有趣的問題。我最近在PDF中引入了書籤,並在關閉文檔時發現問題。讓我們從一個正在發生的事情的示例代碼開始。書籤PdfOutline異常問題關閉文檔

private static String CONTENT = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n" + 
     "\n" + 
     "Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.\n" + 
     "\n" + 
     "Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.\n" + 
     "\n" + 
     "Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.\n" + 
     "\n" + 
     "Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis.\n" + 
     "\n" + 
     "At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.\n"; 

public static void main(String[] args) 
{ 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    Document document = new Document(); 
    try 
    { 
     PdfWriter writer = PdfWriter.getInstance(document, baos); 
     document.open(); 
     PdfOutline root = writer.getRootOutline(); 

     int i = 0; 
     PdfDestination destination = new PdfDestination(PdfDestination.XYZ); 
     PdfOutline outline = new PdfOutline(root, destination, "Section 1"); 
     writer.getDirectContent().localDestination(""+(i++), destination); 
     document.add(new Paragraph(CONTENT)); 

     document.newPage(); 

     destination = new PdfDestination(PdfDestination.XYZ); 
     outline = new PdfOutline(root, destination, "Section 2"); 
     writer.getDirectContent().localDestination(""+(i++), destination); 

     document.close(); 

     PDFEmbeddedManager manager = new PDFEmbeddedManager(); 

     JFrame frame = new JFrame("TEST"); 
     frame.setSize(1024, 768); 
     frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     frame.getContentPane().setLayout(new BorderLayout()); 
     frame.getContentPane().add(manager.getFormView(), BorderLayout.CENTER); 


     manager.showPDF(baos.toByteArray(), ""); 

     frame.setVisible(true); 
    } 
    catch (DocumentException e) 
    { 
     e.printStackTrace(); 
    } 
} 

在將CONTENT添加到文檔後,您會注意到一個newPage()語句,然後是一個大綱。這是麻煩開始的地方。當我嘗試關閉文檔時,我們看到一個異常,這是我在設計中用close()表示的PdfWriter。但是如果我們在newPage()之後刪除書籤,一切都很好,並且沒有例外。

現在對於我的問題,有什麼方法可以讓我們繼續在newPage()之後添加書籤/大綱,這將允許我們無一例外地關閉文檔?有沒有辦法讓我們瀏覽所有的書籤/大綱,修復它們的目的地以指向最後一頁而不是不存在的頁面?任何幫助和洞察力非常感謝。謝謝!

編輯:

這裏是個例外:

Exception in thread "main" java.lang.RuntimeException: The page 2 was requested but the document has only 1 pages. 

編輯2:

主要是,我想實現的是顯示第2節中的書籤,即使第2節有內容與否。由於在第1節結尾處調用newPage(),然後添加第2節大綱但不添加內容,所以引發異常。有沒有辦法讓我繼續添加第2部分大綱/書籤,而不必擔心第2部分是否將內容添加到新頁面?

回答

1

什麼是我們在newPage()之後繼續添加書籤/大綱的好方法,這將允許我們無一例外地關閉文檔?

newPage()之後使用輪廓不足以觸發您的問題。這是必不可少的,你不添加任何內容newPage()後,只有書籤。

會出現以下情況:

  • newPage()使得iText的完成當前(第一)頁並開始一個新的(第二)一個在內存中。
  • localDestination(...)初始化目標指向現在的當前頁面2.
  • close()還有現在的當前第2頁上沒有內容,它,因此,不寫入PDF。
  • close()書寫書籤時,iText發現在不存在的頁面上有書籤目的地並引發異常。

通過在設置目的地後向文檔添加內容,您可以輕鬆防止發生該異常。

... 
    writer.getDirectContent().localDestination(""+(i++), destination); 
    document.add(new Paragraph("x")); // <<<<< Adds content to the page the destination points to 

    document.close(); 

工作得很好。

因此,一個好辦法,繼續添加書籤/外形的newPage()後是確保你設置書籤目的地後添加內容。

2

我打算更新mkl的答案,但最後我決定增加一個額外的答案,因爲這個問題有一個非常具體的原因需要澄清。

你的異常告訴你,你正試圖鏈接到第2頁,但該文檔只有一個頁面。爲什麼你的文件只有一個頁面?

當您觸發document.newPage()時,只有當前頁面不是空白時纔會創建新頁面。這是設計原因,因爲newPage()也是由iText內部觸發的,過去的經驗告訴我們,這經常導致不需要的空白頁面。

如果要重寫此沒有添加內容(由MKL的建議),你可以使用下面的一行:

writer.setPageEmpty(false); 

當一個新的頁面創建標誌pageEmptytrue,直到你加入內容。您可以使用setPageEmpty()方法將此標誌設置爲false。如果你這樣做,你的文檔將有超過1頁。請參閱NewPage示例以瞭解該機制的工作原理。

+0

+1;啊,有趣的細節。 – mkl

+0

會發生什麼,我們有很多部分我們添加到PDF中;有些部分可能不會被添加而其他部分被添加。每個部分都以newPage()結束,以準備下一部分。基本上,我們的問題是我們希望看到一個書籤,其中的部分應該是在哪裏添加內容,並且在處理部分之前首先添加輪廓。例如,爲Section A添加Ouline並將其內容添加到PDF和newPage()。 B節提綱增加了但沒有內容,關閉文檔 - >異常。關於我們可以做什麼的任何想法?我們希望看到B部分的書籤。 – GKproggy

+0

另外,我寧願將setPageEmpty()設置爲true,因爲多個部分可能會連續調用newPage()而不添加單個內容。 – GKproggy