From 2a68c0e2bb6dabae2155e96dc325e30908d08aea Mon Sep 17 00:00:00 2001 From: Amitabh Tiwari Date: Fri, 17 Sep 2021 07:31:41 +0530 Subject: [PATCH] Html2pdf using open pdf (#11178) * Added inital changes html to pdf using openPdf * Added changes to pdf for external style * Added chnages via flying saucer * Added changes ti fix the issue * Added inital changes * Simplyfied the core logic * Created a sperate package * Added changes for making it more modular * Added Image attribute update * Added chnages to add images * Added changes * Style validation * Added changes to fix the styles * Review comments updates * Corrected the versions * Fixed the review commit * Added changes to fix the indendation issue Co-authored-by: Amitabh.Tiwari --- pdf/pom.xml | 24 ++++++++ .../pdf/openpdf/CustomElementFactoryImpl.java | 56 ++++++++++++++++++ .../openpdf/Html2PdfUsingFlyingSaucer.java | 53 +++++++++++++++++ .../pdf/openpdf/Html2PdfUsingOpenHtml.java | 55 +++++++++++++++++ pdf/src/main/resources/html2pdf.pdf | Bin 0 -> 15570 bytes pdf/src/main/resources/htmlforopenpdf.html | 26 ++++++++ pdf/src/main/resources/style.css | 6 ++ 7 files changed, 220 insertions(+) create mode 100644 pdf/src/main/java/com/baeldung/pdf/openpdf/CustomElementFactoryImpl.java create mode 100644 pdf/src/main/java/com/baeldung/pdf/openpdf/Html2PdfUsingFlyingSaucer.java create mode 100644 pdf/src/main/java/com/baeldung/pdf/openpdf/Html2PdfUsingOpenHtml.java create mode 100644 pdf/src/main/resources/html2pdf.pdf create mode 100644 pdf/src/main/resources/htmlforopenpdf.html create mode 100644 pdf/src/main/resources/style.css diff --git a/pdf/pom.xml b/pdf/pom.xml index fb9508156e..6bd1d97402 100644 --- a/pdf/pom.xml +++ b/pdf/pom.xml @@ -71,6 +71,26 @@ flying-saucer-pdf ${flying-saucer-pdf.version} + + org.xhtmlrenderer + flying-saucer-pdf-openpdf + ${flying-saucer-pdf-openpdf.version} + + + org.jsoup + jsoup + ${jsoup.version} + + + com.openhtmltopdf + openhtmltopdf-core + ${open-html-pdf-core.version} + + + com.openhtmltopdf + openhtmltopdf-pdfbox + ${open-html-pdfbox.version} + @@ -93,6 +113,10 @@ 3.15 3.0.11.RELEASE 9.1.20 + 1.0.6 + 1.0.6 + 9.1.22 + 1.14.2 \ No newline at end of file diff --git a/pdf/src/main/java/com/baeldung/pdf/openpdf/CustomElementFactoryImpl.java b/pdf/src/main/java/com/baeldung/pdf/openpdf/CustomElementFactoryImpl.java new file mode 100644 index 0000000000..d8256a68f7 --- /dev/null +++ b/pdf/src/main/java/com/baeldung/pdf/openpdf/CustomElementFactoryImpl.java @@ -0,0 +1,56 @@ +package com.baeldung.pdf.openpdf; + +import java.io.FileInputStream; +import java.io.InputStream; + +import org.apache.commons.io.IOUtils; +import org.w3c.dom.Element; +import org.xhtmlrenderer.extend.FSImage; +import org.xhtmlrenderer.extend.ReplacedElement; +import org.xhtmlrenderer.extend.ReplacedElementFactory; +import org.xhtmlrenderer.extend.UserAgentCallback; +import org.xhtmlrenderer.layout.LayoutContext; +import org.xhtmlrenderer.pdf.ITextFSImage; +import org.xhtmlrenderer.pdf.ITextImageElement; +import org.xhtmlrenderer.render.BlockBox; +import org.xhtmlrenderer.simple.extend.FormSubmissionListener; + +import com.lowagie.text.Image; + +public class CustomElementFactoryImpl implements ReplacedElementFactory { + @Override + public ReplacedElement createReplacedElement(LayoutContext lc, BlockBox box, UserAgentCallback uac, int cssWidth, int cssHeight) { + Element e = box.getElement(); + String nodeName = e.getNodeName(); + if (nodeName.equals("img")) { + String imagePath = e.getAttribute("src"); + try { + InputStream input = new FileInputStream("src/main/resources/" + imagePath); + byte[] bytes = IOUtils.toByteArray(input); + Image image = Image.getInstance(bytes); + FSImage fsImage = new ITextFSImage(image); + if (cssWidth != -1 || cssHeight != -1) { + fsImage.scale(cssWidth, cssHeight); + } else { + fsImage.scale(2000, 1000); + } + return new ITextImageElement(fsImage); + } catch (Exception e1) { + e1.printStackTrace(); + } + } + return null; + } + + @Override + public void reset() { + } + + @Override + public void remove(Element e) { + } + + @Override + public void setFormSubmissionListener(FormSubmissionListener listener) { + } +} \ No newline at end of file diff --git a/pdf/src/main/java/com/baeldung/pdf/openpdf/Html2PdfUsingFlyingSaucer.java b/pdf/src/main/java/com/baeldung/pdf/openpdf/Html2PdfUsingFlyingSaucer.java new file mode 100644 index 0000000000..927d85a4cb --- /dev/null +++ b/pdf/src/main/java/com/baeldung/pdf/openpdf/Html2PdfUsingFlyingSaucer.java @@ -0,0 +1,53 @@ +package com.baeldung.pdf.openpdf; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.xhtmlrenderer.layout.SharedContext; +import org.xhtmlrenderer.pdf.ITextRenderer; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class Html2PdfUsingFlyingSaucer { + + private static final String HTML_INPUT = "src/main/resources/htmlforopenpdf.html"; + private static final String PDF_OUTPUT = "src/main/resources/html2pdf.pdf"; + + public static void main(String[] args) { + try { + Html2PdfUsingFlyingSaucer htmlToPdf = new Html2PdfUsingFlyingSaucer(); + htmlToPdf.generateHtmlToPdf(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void generateHtmlToPdf() throws Exception { + File inputHTML = new File(HTML_INPUT); + Document inputHtml = createWellFormedHtml(inputHTML); + File outputPdf = new File(PDF_OUTPUT); + xhtmlToPdf(inputHtml, outputPdf); + } + + private Document createWellFormedHtml(File inputHTML) throws IOException { + Document document = Jsoup.parse(inputHTML, "UTF-8"); + document.outputSettings() + .syntax(Document.OutputSettings.Syntax.xml); + return document; + } + + private void xhtmlToPdf(Document xhtml, File outputPdf) throws Exception { + try (OutputStream outputStream = new FileOutputStream(outputPdf)) { + ITextRenderer renderer = new ITextRenderer(); + SharedContext sharedContext = renderer.getSharedContext(); + sharedContext.setPrint(true); + sharedContext.setInteractive(false); + sharedContext.setReplacedElementFactory(new CustomElementFactoryImpl()); + renderer.setDocumentFromString(xhtml.html()); + renderer.layout(); + renderer.createPDF(outputStream); + } + } +} diff --git a/pdf/src/main/java/com/baeldung/pdf/openpdf/Html2PdfUsingOpenHtml.java b/pdf/src/main/java/com/baeldung/pdf/openpdf/Html2PdfUsingOpenHtml.java new file mode 100644 index 0000000000..bc83da6102 --- /dev/null +++ b/pdf/src/main/java/com/baeldung/pdf/openpdf/Html2PdfUsingOpenHtml.java @@ -0,0 +1,55 @@ +package com.baeldung.pdf.openpdf; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.FileSystems; + +import org.jsoup.Jsoup; +import org.jsoup.helper.W3CDom; +import org.jsoup.nodes.Document; + +import com.openhtmltopdf.pdfboxout.PdfRendererBuilder; + +public class Html2PdfUsingOpenHtml { + + private static final String HTML_INPUT = "src/main/resources/htmlforopenpdf.html"; + private static final String PDF_OUTPUT = "src/main/resources/html2pdf.pdf"; + + public static void main(String[] args) { + try { + Html2PdfUsingOpenHtml htmlToPdf = new Html2PdfUsingOpenHtml(); + htmlToPdf.generateHtmlToPdf(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void generateHtmlToPdf() throws IOException { + File inputHTML = new File(HTML_INPUT); + Document doc = createWellFormedHtml(inputHTML); + xhtmlToPdf(doc, PDF_OUTPUT); + } + + private Document createWellFormedHtml(File inputHTML) throws IOException { + Document document = Jsoup.parse(inputHTML, "UTF-8"); + document.outputSettings() + .syntax(Document.OutputSettings.Syntax.xml); + return document; + } + + private void xhtmlToPdf(Document doc, String outputPdf) throws IOException { + try (OutputStream os = new FileOutputStream(outputPdf)) { + String baseUri = FileSystems.getDefault() + .getPath("src/main/resources/") + .toUri() + .toString(); + PdfRendererBuilder builder = new PdfRendererBuilder(); + builder.withUri(outputPdf); + builder.toStream(os); + builder.withW3cDocument(new W3CDom().fromJsoup(doc), baseUri); + builder.run(); + } + } +} diff --git a/pdf/src/main/resources/html2pdf.pdf b/pdf/src/main/resources/html2pdf.pdf new file mode 100644 index 0000000000000000000000000000000000000000..877ff4cacd94862e6b9bf5132e3bc548e896435e GIT binary patch literal 15570 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 + + + + + +
+

Hello Baeldung!

+ + +
+

This is the tutorial to convert html to pdf.

+
+
+ + \ No newline at end of file diff --git a/pdf/src/main/resources/style.css b/pdf/src/main/resources/style.css new file mode 100644 index 0000000000..381ffadf00 --- /dev/null +++ b/pdf/src/main/resources/style.css @@ -0,0 +1,6 @@ +.myclass{ + font-family: Helvetica, sans-serif; + font-size:25; + font-weight: normal; + color: blue; +} \ No newline at end of file