Есть ли способ улучшить производительность FlyingSaucer? - PullRequest
2 голосов
/ 25 марта 2011

Я следовал этой статье , чтобы использовать FlyingSaucer для конвертации XHTML в PDF, и он великолепен, но имеет один серьезный недостаток ... он невероятно медленный!

Я считаю, что эторендеринг PDF из XHTML занимает от 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>

Кто-нибудь знает, как улучшить производительность FlyingSaucer?

Если это не удастся, сможет ли кто-нибудь порекомендовать альтернативную библиотеку Java, которая эффективна для рендеринга PDF из URL в (X) HTML-документ с внешнимCSS и изображения, сгенерированные из URL?

Ответы [ 4 ]

15 голосов
/ 05 августа 2011

Я столкнулся с той же проблемой, что и Эдд.

К сожалению, следующий подход не сработал 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();

Что в итоге дало трюк, так это следующие строки:-в Java EntityResolver для разрешения DTD он стал намного быстрее.

4 голосов
/ 27 марта 2011

Проблема в том, что вы, вероятно, используете этот код из связанной статьи:

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 не будет разрешен Flying Saucer.Если вы хотите загрузить Document, а не установить URL, см.

2 голосов
/ 25 марта 2011

Позвольте мне начать с того, что я использовал ваш пример кода и образец xhtml, и он «работал за 2675 мс».

Я скачал flyingsaucer 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 вы используете и на какой платформе?Также какую версию flyingsaucer вы используете?

2 голосов
/ 25 марта 2011

Я бы сделал 2 рекомендации:

  1. Профиль.

  2. Оберните OutputStream в BufferedOutputStream

  3. Профиль.(Упс ... я повторяюсь. Ну, вы поняли.)

...