Skip to content

Commit

Permalink
simplify API for creating PDF: now user needs to write less code to g…
Browse files Browse the repository at this point in the history
…enerate PDF from HTML

This commits adds 2 new apis:
1. class Html2Pdf   (a single method for generating PDF from HTML)
2. renderer.createPDF(doc, os)   (instead of old sequence `setDocument`, `layout`, `createPDF`)
  • Loading branch information
asolntsev committed Mar 4, 2024
1 parent ae7b50e commit 80a757b
Show file tree
Hide file tree
Showing 11 changed files with 122 additions and 124 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,10 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.net.URL;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.logging.Level;
Expand Down Expand Up @@ -77,6 +79,10 @@ private XMLResource(InputSource source) {
super(source);
}

public static XMLResource load(URL source) {
return load(new InputSource(source.toString()));
}

public static XMLResource load(InputStream stream) {
return XML_RESOURCE_BUILDER.createXMLResource(new XMLResource(stream));
}
Expand All @@ -89,6 +95,10 @@ public static XMLResource load(Reader reader) {
return XML_RESOURCE_BUILDER.createXMLResource(new XMLResource(new InputSource(reader)));
}

public static XMLResource load(String xml) {
return load(new StringReader(xml));
}

public static XMLResource load(Source source) {
return XML_RESOURCE_BUILDER.createXMLResource(source);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,16 +339,16 @@ private void renderPDF(Document doc) {
String msgToUser;
try (FileOutputStream fos = new FileOutputStream(f)) {
BufferedOutputStream bos = new BufferedOutputStream(fos);
renderer.setDocument(doc, null, new XhtmlNamespaceHandler());

ITextFontResolver resolver = renderer.getFontResolver();
// TODO: encoding is hard-coded as IDENTITY_H; maybe give user option to override
resolver.addFont(
fontPathTF.getText(),
BaseFont.IDENTITY_H,
BaseFont.EMBEDDED
);
renderer.layout();
renderer.createPDF(bos);
renderer.getSharedContext().setNamespaceHandler(new XhtmlNamespaceHandler());
renderer.createPDF(doc, bos);

msgToUser = "Rendered PDF: " + f.getCanonicalPath();
} catch (DocumentException | IOException e) {
Expand Down
4 changes: 1 addition & 3 deletions flying-saucer-examples/src/main/java/PDFRender.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,7 @@ public static void createPDF(String url, String pdf) throws IOException, Documen

Document doc = XMLResource.load(new InputSource(url)).getDocument();

renderer.setDocument(doc, url);
renderer.layout();
renderer.createPDF(os);
renderer.createPDF(doc, os);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,35 +289,31 @@ public void loadPage(final String url_text) {
}
}

public void exportToPdf( String path )
{
if (manager.getBaseURL() != null) {
setStatus( "Exporting to " + path + "..." );
try (OutputStream os = Files.newOutputStream(Paths.get(path))) {
try {
ITextRenderer renderer = new ITextRenderer();

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(manager.getBaseURL());

PDFCreationListener pdfCreationListener = new XHtmlMetaToPdfInfoAdapter( doc );
renderer.setListener( pdfCreationListener );

renderer.setDocument(manager.getBaseURL());
renderer.layout();

renderer.createPDF(os);
setStatus( "Done export." );
public void exportToPdf(String path) {
if (manager.getBaseURL() != null) {
setStatus("Exporting to " + path + "...");
try (OutputStream os = Files.newOutputStream(Paths.get(path))) {
try {
ITextRenderer renderer = new ITextRenderer();

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(manager.getBaseURL());

PDFCreationListener pdfCreationListener = new XHtmlMetaToPdfInfoAdapter(doc);
renderer.setListener(pdfCreationListener);

renderer.createPDF(doc, os);
setStatus("Done export.");
} catch (Exception e) {
XRLog.general(Level.SEVERE, "Could not export PDF.", e);
e.printStackTrace();
setStatus("Error exporting to PDF.");
}
} catch (Exception e) {
XRLog.general(Level.SEVERE, "Could not export PDF.", e);
e.printStackTrace();
setStatus( "Error exporting to PDF." );
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}

private void handlePageLoadFailed(String url_text, XRRuntimeException ex) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,18 @@
package org.xhtmlrenderer.pdf;

import com.codeborne.pdftest.PDF;
import com.lowagie.text.DocumentException;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.xhtmlrenderer.resource.FSEntityResolver;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;

import static com.codeborne.pdftest.assertj.Assertions.assertThat;
import static java.lang.Thread.currentThread;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.Executors.newFixedThreadPool;
import static java.util.concurrent.Executors.newScheduledThreadPool;
Expand Down Expand Up @@ -73,29 +65,9 @@ private void verifyPdf(byte[] pdfBytes) {
}

private byte[] generatePdf(String htmlPath) {
ITextRenderer renderer = new ITextRenderer();
renderer.getSharedContext().setMedia("pdf");
renderer.getSharedContext().setInteractive(false);
renderer.getSharedContext().getTextRenderer().setSmoothingThreshold(0);

URL htmlUrl = requireNonNull(Thread.currentThread().getContextClassLoader().getResource(htmlPath), () -> "Test resource not found: " + htmlPath);

try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
builder.setEntityResolver(FSEntityResolver.instance());

Document doc = builder.parse(htmlUrl.openStream());

renderer.setDocument(doc, htmlUrl.toString());
renderer.layout();

ByteArrayOutputStream bos = new ByteArrayOutputStream();
renderer.createPDF(bos);
return bos.toByteArray();
}
catch (DocumentException | IOException | SAXException | ParserConfigurationException e) {
throw new IllegalArgumentException(e);
}
URL htmlUrl = requireNonNull(currentThread().getContextClassLoader().getResource(htmlPath),
() -> "Test resource not found: " + htmlPath);
return Html2Pdf.fromUrl(htmlUrl);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.xhtmlrenderer.resource.XMLResource;
import org.xml.sax.InputSource;

import javax.annotation.ParametersAreNonnullByDefault;
import java.io.File;
Expand Down Expand Up @@ -51,16 +50,13 @@ public void convertComplexHtmlToPdf() throws IOException, DocumentException {
}

private static PDF generatePDF(URL source, File output) throws IOException, DocumentException {
Document doc = XMLResource.load(source).getDocument();

try (OutputStream os = newOutputStream(output.toPath())) {
ITextRenderer renderer = new ITextRenderer();
ResourceLoaderUserAgent callback = new ResourceLoaderUserAgent(renderer.getOutputDevice(), renderer.getSharedContext().getDotsPerPixel());
renderer.getSharedContext().setUserAgentCallback(callback);

Document doc = XMLResource.load(new InputSource(source.toString())).getDocument();

renderer.setDocument(doc, source.toString());
renderer.layout();
renderer.createPDF(os);
renderer.createPDF(doc, os);
}
log.info("Rendered {}{} to PDF: {}", source, lineSeparator(), output.toURI());
return new PDF(output);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

import com.codeborne.pdftest.PDF;
import com.lowagie.text.DocumentException;
import org.apache.pdfbox.io.IOUtils;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.xhtmlrenderer.resource.XMLResource;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringReader;

import static com.codeborne.pdftest.assertj.Assertions.assertThat;

Expand All @@ -20,20 +20,13 @@ public class SimpleHtmlTest {

@Test
public void simplePdf() throws DocumentException, IOException {
ITextRenderer renderer = new ITextRenderer();

String htmlContent = "<!DOCTYPE html><html><body><h1>My First Heading</h1><p>My first paragraph.</p></body></html>";

renderer.setDocumentFromString(htmlContent);

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
renderer.layout();
renderer.createPDF(outputStream);
renderer.finishPDF();

File file = new File("target/simple.pdf");
try (FileOutputStream o = new FileOutputStream(file)) {
IOUtils.copy(new ByteArrayInputStream(outputStream.toByteArray()), o);
ITextRenderer renderer = new ITextRenderer();
Document source = XMLResource.load(new StringReader(htmlContent)).getDocument();
renderer.createPDF(source, o);
}
log.info("Generated PDF: {}", file.getAbsolutePath());

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.xhtmlrenderer.pdf;

import com.lowagie.text.DocumentException;
import org.w3c.dom.Document;
import org.xhtmlrenderer.resource.FSEntityResolver;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.net.URL;

import static java.util.Objects.requireNonNull;

public class Html2Pdf {
public static byte[] fromClasspathResource(String fileName) {
URL htmlUrl = requireNonNull(Thread.currentThread().getContextClassLoader().getResource(fileName),
() -> "Resource not found in classpath: " + fileName);
return fromUrl(htmlUrl);
}

public static byte[] fromUrl(URL html) {
ITextRenderer renderer = new ITextRenderer();
renderer.getSharedContext().setMedia("pdf");
renderer.getSharedContext().setInteractive(false);
renderer.getSharedContext().getTextRenderer().setSmoothingThreshold(0);

try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
builder.setEntityResolver(FSEntityResolver.instance());

Document doc = builder.parse(html.toString());
return renderer.createPDF(doc);
}
catch (DocumentException | IOException | SAXException | ParserConfigurationException e) {
throw new IllegalArgumentException(e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import javax.xml.transform.stream.StreamResult;
import java.awt.*;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
Expand Down Expand Up @@ -180,8 +181,8 @@ public void setDocument(Document doc, String url) {
setDocument(doc, url, new XhtmlNamespaceHandler());
}

@Deprecated
public void setDocument(File file) throws IOException {

File parent = file.getAbsoluteFile().getParentFile();
setDocument(loadDocument(file.toURI().toURL().toExternalForm()), (parent == null ? "" : parent.toURI().toURL().toExternalForm()));
}
Expand All @@ -197,6 +198,7 @@ public void setDocumentFromString(String content, String baseUrl) {
setDocument(dom, baseUrl);
}

@Deprecated
public void setDocument(Document doc, String url, NamespaceHandler nsh) {
_doc = doc;

Expand Down Expand Up @@ -245,7 +247,6 @@ public int getPDFXConformance(){
return _pdfXConformance == null ? '0' : _pdfXConformance;
}


public void layout() {
LayoutContext c = newLayoutContext();
BlockBox root = BoxBuilder.createRootBox(c, _doc);
Expand Down Expand Up @@ -285,6 +286,23 @@ private LayoutContext newLayoutContext() {
return result;
}

public byte[] createPDF(Document source) throws DocumentException {
setDocument(source, source.getDocumentURI());
layout();

ByteArrayOutputStream bos = new ByteArrayOutputStream();
createPDF(bos);
finishPDF();
return bos.toByteArray();
}

public void createPDF(Document source, OutputStream os) throws DocumentException {
setDocument(source, source.getDocumentURI());
layout();
createPDF(os);
finishPDF();
}

public void createPDF(OutputStream os) throws DocumentException {
createPDF(os, true, 0);
}
Expand Down
Loading

0 comments on commit 80a757b

Please sign in to comment.