2012-09-20 37 views
0

我正在使用Flying Saucer with IText從HTML文件生成PDF,特別是使用org.xhtmlrenderer.pdf.ITextRenderer類。我的代碼很簡單。生成代碼封裝在一個方法,如下所示:FlyingSaucer ITextRenderer完成錯誤(非平衡保存/恢復和空白PDF)

/* PDfGenerator class only has ONE instance */ 
public PdfGenerator() { 
    this.renderer = new ITextRenderer(); //This is a class variable that only gets instantiated ONCE 
} 

public void generatePDF(String outputFilePath, String htmlContent) { 
    renderer.setDocumentFromString(htmlContent); 
    renderer.layout(); 
    renderer.createPDF(new BufferedOutputStream(
      new FileOutputStream(new File(outputFilePath)), BUFFER_SIZE), true); 
    renderer.finishPDF(); 
} 

編輯:

我的發電機類實際上是由Spring管理作爲一個單獨的對象。我有一個管理員類,有一個ExecutorService充當PDF生成任務的隊列。這位經理使用單身生成器來生成對象。因此,我只是一次性實例化ITextRenderer並重用它。現在我設置我的隊列同時操作多達2個線程。我只是意識到,如果這可能是由於我遇到了兩個線程正在使用我的ONE渲染器渲染兩組獨立PDF的情況。

現在,我只是意識到,我實際上每次渲染調用兩次「完成」!一個在createPDF()錯誤中調用(作爲第二個參數傳遞true),另一個顯式調用finishPDF()

這已經運行了相當長一段時間了,它成功地生成了PDF文件大多數的時間。我已經遇到了兩種不同類型的錯誤偶爾:

  1. 運行時由於不平衡例外保存/恢復狀態運營。示例堆棧跟蹤如下:

    java.lang.RuntimeException: Unbalanced save/restore state operators. 
    at com.lowagie.text.pdf.PdfContentByte.restoreState(Unknown Source) ~[itext-2.0.8.jar:na] 
    at org.xhtmlrenderer.pdf.ITextOutputDevice.setClip(ITextOutputDevice.java:737) ~[core-renderer-R8.jar:na] 
    at org.xhtmlrenderer.pdf.ITextRenderer.paintPage(ITextRenderer.java:387) ~[core-renderer-R8.jar:na] 
    at org.xhtmlrenderer.pdf.ITextRenderer.writePDF(ITextRenderer.java:348) ~[core-renderer-R8.jar:na] 
    at org.xhtmlrenderer.pdf.ITextRenderer.createPDF(ITextRenderer.java:315) ~[core-renderer-R8.jar:na] 
    at org.xhtmlrenderer.pdf.ITextRenderer.createPDF(ITextRenderer.java:280) ~[core-renderer-R8.jar:na] 
    
  2. 生成的PDF包含缺失/變形的部分或最差的空白頁。

對於問題2,我相當確信這是由於調用finishPDF()兩次。但是,對於問題1,在之前會發生對finishPDF()的調用被執行,所以我實際上不知道是否是導致問題的原因。

有沒有人在使用飛碟和iText一起處理這兩個問題的經驗?

+0

請問您可以發佈完整的FS碼嗎?例如。您在哪裏設置文檔。對於2:你使用CSS,pagebreaktags等?這有時會導致空白頁面,也可能是文件末尾有空行或沒有足夠空間存放圖片。 – ollo

+1

順便說一句。如果你刪除'finishPDF()'調用會發生什麼?'createPDF'參數'finish = true'(就像你設置的那樣)不需要第二次完成(但它不應該以負面的方式影響你的pdf)。 – ollo

+0

嗨@ollo,在問題中增加了更多細節。我也意識到也許我實際上同時訪問了渲染器的一個實例,這可能是我遇到上述問題的原因。我原本是這樣設計的,因爲我認爲渲染器的初始化時間太昂貴了......我想知道是否對我創建新的渲染器實例會更好,因此我可以操作併發的PDF生成隊列...並且您去吧,我沿着一條切線去了。無論如何,你能否證實我的發現? :) –

回答

1

我遇到的問題基本上是在不同的線程上同時訪問同一個ITextRenderer實例,從而導致處理當前正在運行的PDF生成作業。

我已經讓Executor服務只使用1個線程,並且使得生成作業是連續的,並且基於我的觀察,只要我一次處理一個,我就可以重複使用相同的ITextRenderer。

我發送了一個查詢,以確認這與飛碟lib的開發者,我只是更新這個帖子,當他們回覆。另外,我只需要弄清楚使用1個線程和1個預先實例化的ITextRenderer實例,或者使用多個線程,但是實例化每個線程的ITextRenderer是否更有效率。

+1

您是否曾經想過爲每個PDF生成實例化ITextRenderer?我發現長壽的ITextRenderers在它的'上下文'中緩存了多達32個圖像,這導致了我的內存不足錯誤。 –

+0

@AnonyChuinard這實際上是非常有用的信息...最近我的應用程序中也出現了一些OOM錯誤。謝謝。 –