2014-02-26 74 views
0

我想使用apache fop從jaxb-object生成pdf文件並生成itext PdfStamper來修改它。由於fop寫入outputStream並且PdfStamper從InputStream讀取,我的想法是使用Piped [I | O]流來完成此操作。這裏是我的嘗試:使用apache fop與PipedOutputStream

public void transform2XSLFO_onthefly(Medium medium, OutputStream out) throws Exception { 
     PipedInputStream pInputPipe = new PipedInputStream(); 
     PipedOutputStream outputTemp = new PipedOutputStream(pInputPipe); 

try { 

     JAXBSource source = new JAXBSource(JAXBContext.newInstance(medium.getClass()) , medium); 

      FOUserAgent userAgent = fopFactory.newFOUserAgent(); 
      // settings 
     Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, userAgent ,outputTemp); 


     InputStream XSLinputStream = xslfoStylesheet.getInputStream(); 
     StreamSource XSLsource = new StreamSource(XSLinputStream); 

     Result res = new SAXResult(fop.getDefaultHandler()); 

     TransformerFactory tf = TransformerFactory.newInstance(); 
     Transformer t = tf.newTransformer(XSLsource); 



     // run transformation 
     t.transform(source, res); 
     // does not come so far, no use closing the stream 
     outputTemp.close(); 

     PdfReader reader = new PdfReader(pInputPipe); 
     pdfStamper = new PdfStamper(reader, out); 
     //..... postProcess... 
     pdfStamper.close(); 

    } catch (Exception ex) { 
     log.error("ERROR", ex); 
    } 

然而,在該行掛起「t.transform(源,RES);」,看起來他正在等待在FOP轉化的中間有東西。它的工作原理採用BypeArrayOutputStream並將其轉換爲InputStream和使用它的PdfStamper輸入:

InputStream pdfInput = new ByteArrayInputStream(((ByteArrayOutputStream) outputTemp).toByteArray()); 

但這些文件可以得到相當大(幾MB),所以我認爲,管道版本將有更好的表現!你怎麼看?

+0

我很確定FOP需要在開始輸出東西之前構建幾乎整個文件。例如,對於目錄的任何前向引用都必須被延遲,直到幾乎處理完所有文件。因此,管道不會爲你買東西。 –

+0

@bobDalgleish我不理解你的評論,或者你錯過了我的意見:我希望fop處理整個文件,然後我想在fop創建它之後鏈接文件的itext操作! –

回答

0

您應該瞭解如何使用PipeInput/OutputStream。 FOP和PdfStamper將需要在不同的線程中運行。基本上,這與FOP本身無關。我相信你會在網絡上找到關於它如何工作的各種例子。如果您對多線程編程不滿意,我建議您將FOP的輸出緩存在一個byte []或一個臨時文件中。

+0

你是對的,我做了一些思考,沒有意義,只有一個線程。畢竟FOP是單線程的,因此必須有一個緩衝區,我不能後處理pdf,而fop仍然在創建它。謝謝 –