繁体   English   中英

有没有办法提高飞碟的性能?

[英]Is there any way improve the performance of 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:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>My First Document</title>
        <style type="text/css"> b { color: green; } </style>
    </head>
    <body>
        <p>
            <b>Greetings Earthlings!</b>
            We've come for your Java.
        </p>
    </body>
</html>

有谁知道如何提高飞碟的性能?

如果做不到这一点,是否有人能够推荐一种替代的 Java 库,该库可以有效地将 PDF 从 URL 呈现为具有外部 CSS 和从 URL 生成的图像的 (X)HTML 文档?

我和 Edd 面临着同样的问题。

遗憾的是,下一个方法不起作用Java DocumentBuilder: xml parsing is very slow? 作者 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。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

加载和解析 DTD 需要很多时间。

如果您正在使用

ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(url); // not setDocument(document)

飞碟不会解决 DTD。 如果要加载Document ,而不是设置 url,请参阅

我会提出2个建议:

  1. 配置文件。

  2. OutputStream包装在BufferedOutputStream

  3. 配置文件。 (哎呀......我在重复自己。好吧,你明白了。)

首先让我说我使用了您的示例代码和示例 xhtml,它“在 2675 毫秒内运行”。

我下载了飞碟R8。 并将其中三个罐子放入我的类路径中。

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 以及在什么平台上? 另外你用的是哪个版本的飞碟?

我们也面临着巨大的性能问题。 生成第一个 PDF 花了将近一分钟。 如果在第一代仍在运行时触发另一代,它们几乎会同时完成。 生成第一个 PDF 后,后续请求的执行速度要快得多。

经过一些分析后,我发现瓶颈是在ITextFontResolver初始化时实例化的ITextRenderer 这是因为解析器从com.lowagie.text.pdf.BaseFont加载了它需要的所有字体,这导致了巨大的延迟。 BaseFont缓存其生成的字体,这解释了并行请求的同时完成和后续请求的加速。

我们的解决方案是在应用程序初始化时加载所需的字体。 这会稍微增加启动时间(但不会增加一分钟,因为它似乎与其他初始化内容并行执行)但允许第一个 PDF 的生成速度与其他 PDF 一样快。 为了触发字体加载,我们刚刚初始化了一个ITextFontResolver实例。 使用 spring 解决方案就像这样简单:

@Component
public class FontLoader  implements InitializingBean {

    @Override
    public void afterPropertiesSet() {
        ITextFontResolver fontResolver = new ITextFontResolver(null);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM