有没有办法提高FlyingSaucer的性能?
我已经按照这篇文章使用FlyingSaucer将XHTML转换为PDF,它很棒,但有一个主要的垮台……它的速度非常慢!
我发现从XHTML渲染PDF需要1到2分钟,无论该页面有多简单。
基本代码:
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import org.xhtmlrenderer.pdf.ITextRenderer; import com.lowagie.text.DocumentException; public class FirstDoc { public static void main(String[] args) throws IOException, DocumentException { String inputFile = "firstdoc.xhtml"; String url = new File(inputFile).toURI().toURL().toString(); String outputFile = "firstdoc.pdf"; OutputStream os = new FileOutputStream(outputFile); ITextRenderer renderer = new ITextRenderer(); renderer.setDocument(url); renderer.layout(); renderer.createPDF(os); os.close(); } }
示例XHTML:
My First Document b { color: green; } Greetings Earthlings! We've come for your Java.
有谁知道如何提高FlyingSaucer的性能?
如果不这样做,是否有人能够推荐一个替代的Java库,它有效地将URL从URL渲染到带有外部CSS的(X)HTML文档和从URL生成的图像?
首先我要说的是,我使用了您的示例代码和示例xhtml,并且它“在2675ms内运行”。
我下载了flyingsaucer R8。 并将三个jar放入我的类路径中。
core-renderer.jar,iText-2.0.8.jar,xml-apis-xerces-2.9.1.jar
我通过使用仪器修改代码来测量运行时间…
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import org.xhtmlrenderer.pdf.ITextRenderer; import com.lowagie.text.DocumentException; public class FirstDoc { public static void main(String[] args) throws IOException, DocumentException { long start = System.currentTimeMillis(); String inputFile = "firstdoc.xhtml"; String url = new File(inputFile).toURI().toURL().toString(); String outputFile = "firstdoc.pdf"; OutputStream os = new FileOutputStream(outputFile); ITextRenderer renderer = new ITextRenderer(); renderer.setDocument(url); renderer.layout(); renderer.createPDF(os); os.close(); long end = System.currentTimeMillis(); System.out.println("Ran in " + (end-start) + "ms"); } }
现在这个库并不是很快,但它似乎也没需要1-2分钟。 所以现在我们需要弄清楚为什么它的运行速度如此之慢。 您能告诉我们您使用的JDK以及使用的平台吗? 你还使用哪个版本的flyingsaucer?
我和Edd面临同样的问题。
遗憾的是,接下来的方法不适用于Java DocumentBuilder:xml解析速度很慢? 由Marek Piechut完全为我 – 我的HTML实体在途中迷路了。
DocumentBuilderFactory fac = DocumentBuilderFactory.newInstance(); fac.setNamespaceAware(false); fac.setValidating(false); fac.setFeature("http://xml.org/sax/features/namespaces", false); fac.setFeature("http://xml.org/sax/features/validation", false); fac.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false); fac.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); DocumentBuilder builder = fac.newDocumentBuilder();
最终诀窍是这些线:
DocumentBuilderFactory fac = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = fac.newDocumentBuilder(); builder.setEntityResolver(FSEntityResolver.instance());
通过使用内置的Java EntityResolver来解析DTD,它获得了更快的速度。
问题是,您可能正在使用链接文章中的此代码:
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document doc = builder.parse(new StringBufferInputStream(buf.toString()));
这样构建器将尝试加载引用的DTD。
加载和解析DTD需要花费大量时间。
如果你正在使用
ITextRenderer renderer = new ITextRenderer(); renderer.setDocument(url); // not setDocument(document)
飞碟不会解决DTD问题。 如果要加载Document
,而不是设置url,请参阅
- 如何在Java中读取格式良好的XML,但是跳过架构?
- 我对此的回答: xhtmlrenderer创建长度为0的PDF
我会提出2条建议:
-
简介它。
-
将
OutputStream
包装在BufferedOutputStream
-
简介它。 (哎呀……我在重复自己。好吧,你得到了照片。)