Konvertieren von HTML in PDF mit iText

Ich bin Entsendung diese Frage, weil viele Entwickler Fragen mehr oder weniger die gleiche Frage in verschiedenen Formen. Ich beantworte diese Frage selbst (ich bin der Gründer/CTO von iText Gruppe), so dass es sein kann, ein "Wiki-Antwort." Wenn der Stack-Überlauf "Dokumentation" - Funktion noch existiert, dies wäre ein guter Kandidat für eine Dokumentation Thema.

Der Quell-Datei:

Ich versuche, konvertieren Sie die folgende HTML-Datei in PDF:

<html>
    <head>
        <title>Colossal (movie)</title>
        <style>
            .poster { width: 120px;float: right; }
            .director { font-style: italic; }
            .description { font-family: serif; }
            .imdb { font-size: 0.8em; }
            a { color: red; }
        </style>
    </head>
    <body>
        <img src="img/colossal.jpg" class="poster" />
        <h1>Colossal (2016)</h1>
        <div class="director">Directed by Nacho Vigalondo</div>
        <div class="description">Gloria is an out-of-work party girl
            forced to leave her life in New York City, and move back home.
            When reports surface that a giant creature is destroying Seoul,
            she gradually comes to the realization that she is somehow connected
            to this phenomenon.
        </div>
        <div class="imdb">Read more about this movie on
            <a href="www.imdb.com/title/tt4680182">IMDB</a>
        </div>
    </body>
</html>

In einem browser, der dieses HTML sieht wie folgt aus:

Konvertieren von HTML in PDF mit iText

Die Probleme, die ich gestoßen:

HTMLWorker nicht der CSS berücksichtigen überhaupt

Wenn ich HTMLWorker brauche ich zum erstellen einer ImageProvider um einen Fehler vermeiden, informiert mich, dass das Bild nicht gefunden werden kann. Ich muss auch zum erstellen einer StyleSheet Instanz zu ändern einige Formatvorlagen:

public static class MyImageFactory implements ImageProvider {
    public Image getImage(String src, Map<String, String> h,
            ChainedProperties cprops, DocListener doc) {
        try {
            return Image.getInstance(
                String.format("resources/html/img/%s",
                    src.substring(src.lastIndexOf("/") + 1)));
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }    
}

public static void main(String[] args) throws IOException, DocumentException {
    Document document = new Document();
    PdfWriter.getInstance(document, new FileOutputStream("results/htmlworker.pdf"));
    document.open();
    StyleSheet styles = new StyleSheet();   
    styles.loadStyle("imdb", "size", "-3");
    HTMLWorker htmlWorker = new HTMLWorker(document, null, styles);
    HashMap<String,Object> providers = new HashMap<String, Object>();
    providers.put(HTMLWorker.IMG_PROVIDER, new MyImageFactory());
    htmlWorker.setProviders(providers);
    htmlWorker.parse(new FileReader("resources/html/sample.html"));
    document.close();   
}

Das Ergebnis sieht wie folgt aus:

Konvertieren von HTML in PDF mit iText

Aus irgendeinem Grund HTMLWorker zeigt auch den Inhalt der <title> tag. Ich weiß nicht, wie dies zu vermeiden. Die CSS-Datei in der Kopfzeile nicht analysiert an alle, ich haben, definieren Sie die Stile in meinem code, mit dem StyleSheet Objekt.

Wenn ich mir meinen code sehe ich, dass viele Objekte und Methoden, die ich verwende sind veraltet:

Konvertieren von HTML in PDF mit iText

Also habe ich beschlossen, ein upgrade auf die Verwendung von XML-Arbeiter.


Bilder nicht gefunden werden, wenn die Verwendung von XML Worker

Habe ich versucht den folgenden code:

public static final String DEST = "results/xmlworker1.pdf";
public static final String HTML = "resources/html/sample.html";
public void createPdf(String file) throws IOException, DocumentException {
    Document document = new Document();
    PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
    document.open();
    XMLWorkerHelper.getInstance().parseXHtml(writer, document,
            new FileInputStream(HTML));
    document.close();
}

Dies führte in der folgenden PDF-Datei:

Konvertieren von HTML in PDF mit iText

Anstelle von Times Roman, der Standard-schriftart Helvetica verwendet wird; dies ist typisch für iText (ich sollte definiert eine schriftart, die explizit in meinem HTML). Ansonsten werden die CSS scheint, respektiert zu werden, aber das Bild fehlt, und ich nicht eine Fehlermeldung erhalten.

Mit HTMLWorker, wird eine Ausnahme geworfen wurde, und ich war in der Lage, das problem zu beheben durch die Einführung einer ImageProvider. Mal sehen, ob das funktioniert für XML Worker.

Nicht alle CSS-Stile werden unterstützt XML-Worker

Angepasst ich meinen code wie folgt:

public static final String DEST = "results/xmlworker2.pdf";
public static final String HTML = "resources/html/sample.html";
public static final String IMG_PATH = "resources/html/";
public void createPdf(String file) throws IOException, DocumentException {
    Document document = new Document();
    PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
    document.open();

    CSSResolver cssResolver =
            XMLWorkerHelper.getInstance().getDefaultCssResolver(true);
    HtmlPipelineContext htmlContext = new HtmlPipelineContext(null);
    htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
    htmlContext.setImageProvider(new AbstractImageProvider() {
        public String getImageRootPath() {
            return IMG_PATH;
        }
    });

    PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
    HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
    CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);

    XMLWorker worker = new XMLWorker(css, true);
    XMLParser p = new XMLParser(worker);
    p.parse(new FileInputStream(HTML));

    document.close();
}

Mein code ist viel länger, aber jetzt wird das Bild gerendert:

Konvertieren von HTML in PDF mit iText

Das Bild größer ist, als wenn ich es gerendert mit HTMLWorker was mir sagt, dass das CSS-Attribut width für die poster Klasse berücksichtigt, aber die float - Attribut ignoriert. Wie kann ich dieses Problem beheben?

Bleibt die Frage:

Also die Frage läuft darauf hinaus, diese: ich habe einen bestimmten HTML-Datei, die ich versuche, in PDF zu konvertieren. Ich habe gegangen durch eine Menge von Arbeit, die Befestigung ein problem nach dem anderen, aber es ist eine bestimmten problem, dass ich nicht lösen kann: wie kann ich machen iText Respekt CSS, definiert die position eines Elements, wie float: right?

Zusätzliche Frage:

Wenn meine HTML enthält die Elemente bilden (wie <input>), die form-Elemente werden ignoriert.

Warum die enge Abstimmung mit dem Grund "zu breit"? Dies ist ein sehr spezifische Frage mit sehr spezifische Beispiele. Ich fügte hinzu, source code, dass die Ergebnisse in sehr spezifische Probleme, die nicht gelöst werden kann mit der alten iText Funktionalität. Die Antwort zeigt, dass mit der neuen version löst das problem angemessen. Man könnte argumentieren, dass es doppelte Fragen (ich könnte Dutzende von Duplikaten), aber die Duplikate sind nicht so spezifisch, und wir brauchen wirklich eine Referenz zu beantworten. Nun, die Dokumentation auf, SO ging den Bach runter, das ist der einzige Weg, um eine gute Frage und eine gute Antwort auf SO.
Denn es gibt nicht ein spezifische Frage. Ungefragt "Frage" hier ist, wie konvertiere ich diese HTML-zu PDF. Die ganze Sache ist zu breit. Und der gesamte Stil scheint eine schlechte Passform für das format, diese Dokumentation nicht.
Sie müssen auch nicht offenlegen, Ihre Verbundenheit mit der Bibliothek in der "Frage" oder "Antwort".
OK, die updates sind gemacht (die konkrete Frage + die Zugehörigkeit zu iText-Gruppe). Sind Sie jetzt glücklich, @jmoerdyk?
Es gibt bereits viele Hinweise auf diese Frage in den Kommentaren: stackoverflow.com/questions/47872246 stackoverflow.com/questions/47852780 stackoverflow.com/questions/47830668 stackoverflow.com/questions/47787253 stackoverflow.com/questions/47808275, Wie viele Fragen sollte ich hinzufügen, Sie zu überzeugen, dass dieses Q&A sind nützlich? Wenn ich kann nicht Sie überzeugen, bitte Wiedereinführung der SO-Dokumentation der Funktionalität, so dass ich hinzufügen kann, diese Inhalte als eine Dokumentation, ein Thema (oder eine alternative Lösung).

InformationsquelleAutor Bruno Lowagie | 2017-12-19

Schreibe einen Kommentar