2014-02-26 36 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仍然在创建它。谢谢 –