使用Openhtmltopdf,PDFBox在Java中将HTML转换为PDF
在使用Flying Saucer在Java中将HTML转换为PDF的文章OpenPDF中,我们看到了一种将HTML转换为PDF的方法,在本教程中,我们将了解如何使用Openhtmltopdf,PDFBox和jsoup在Java中将HTML转换为PDF。
使用Openhtmltopdf将HTML转换为PDF –工作原理
Open HTML to PDF是一个纯Java库,用于使用CSS 2.1进行布局和格式设置来呈现任意格式正确的XML / XHTML(甚至HTML5),并输出为PDF或者图像。将HTML转换为PDF的步骤如下-
- 第一步是确保我们使用jsoup将HTML用作输入并解析它以返回格式正确的HTML,从而形成格式正确的HTML。
- Openhtmltopdf使用CSS生成XHTML的呈现形式,以进行布局和格式设置。
- PDFBox用于从该渲染表示形式生成PDF文档。
Maven依赖
Openhtmltopdf,jsoup和PDFBox的Apache Maven依赖关系如下-
<dependency> <!-- ALWAYS required --> <groupId>com.openhtmltopdf</groupId> <artifactId>openhtmltopdf-core</artifactId> <version>${openhtml.version}</version> </dependency> <dependency> <!-- Required for PDF output. --> <groupId>com.openhtmltopdf</groupId> <artifactId>openhtmltopdf-pdfbox</artifactId> <version>${openhtml.version}</version> </dependency> <!-- jsoup --> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.13.1</version> </dependency>
在POM的属性部分添加
<properties> <openhtml.version>1.0.4</openhtml.version> </properties>
使用Openhtmltopdf和PDFBox Java程序将HTML转换为PDF
在将HTML转换为PDF的过程中,Java程序试图解决三个常见问题:
- 如何使用<img src ="" ..>标签在PDF中显示以HTML格式显示的图像。
- 如何添加任何特定的网络字体。
- 如何确保HTML中使用的外部CSS也可以用来设置生成的PDF的样式。
示例程序使用的文件夹结构如下所示。在PDFBox文件夹中,我们有HTML文件,真型字体文件和png图像文件,而PDFBox / css文件夹中有css文件。
- PDFBox MyPage.html Gabriola.ttf image.png --css mystyles.css
MyPage.html
这是我们必须转换为PDF的HTML。
<html lang="en"> <head> <title>MyPage</title> <style type="text/css"> body{background-color: powderblue;} </style> <link href="css/mystyles.css" rel="stylesheet" > </head> <body> <h1>Convert HTML to PDF</h1> <p>Here is an embedded image</p> <img src="image.png" width="250" height="150"> <p style="color:red">Styled text using Inline CSS</p> <i>This is italicised text</i> <p class="fontclass">This text uses the styling from font face font</p> <p class="myclass">This text uses the styling from external CSS class</p> </body> </html>
如我们所见,此HTML将内联CSS与<p>标记一起使用
<p style="color:red">Styled text using Inline CSS</p>
在<style> </ style>标记中使用内部CSS,还使用外部CSS。所有这些样式也应反映在PDF中。
还有一个带有相对路径的图像。
mystyles.css
在css中,@ font-face规则用于指定字体和可以找到它的URL。
使用@page规则指定在打印文档时要使用的CSS属性。
@font-face { font-family: myFont; src: url("../Gabriola.ttf"); } .fontclass{ font-family: myFont; } @Page { size: 8.5in 11in; margin: 1in; } .myclass{ font-family: Helvetica, sans-serif; font-size:25; font-weight: normal; color: blue; }
这就是在Chrome浏览器中呈现HTML的方式。
Java程序将HTML转换为PDF
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.w3c.dom.Document; import com.openhtmltopdf.pdfboxout.PdfRendererBuilder; public class HtmlToPdf { public static void main(String[] args) { try { // Source HTML file String inputHTML = "F:\theitroad\Java\Java Programs\PDF using Java\PDFBox\MyPage.html"; // Generated PDF file name String outputPdf = "F:\theitroad\Java\Java Programs\PDF using Java\PDFBox\Output.pdf"; htmlToPdf(inputHTML, outputPdf); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private static Document html5ParseDocument(String inputHTML) throws IOException{ org.jsoup.nodes.Document doc; System.out.println("parsing ..."); doc = Jsoup.parse(new File(inputHTML), "UTF-8"); System.out.println("parsing done ..." + doc); return new W3CDom().fromJsoup(doc); } private static void htmlToPdf(String inputHTML, String outputPdf) throws IOException { Document doc = html5ParseDocument(inputHTML); String baseUri = FileSystems.getDefault() .getPath("F:/", "theitroad/Java/", "Java Programs/PDF using Java/PDFBox/") .toUri() .toString(); OutputStream os = new FileOutputStream(outputPdf); PdfRendererBuilder builder = new PdfRendererBuilder(); builder.withUri(outputPdf); builder.toStream(os); // using absolute path here builder.useFont(new File("F:\theitroad\Java\Java Programs\PDF using Java\PDFBox\Gabriola.ttf"), "Gabriola"); builder.withW3cDocument(doc, baseUri); //builder.useUriResolver(new MyResolver()); builder.run(); System.out.println("PDF generation completed"); os.close(); } }
在程序中,要注意的一些重要点是:
- 在html5ParseDocument方法中,jsoup.parse()方法用于生成格式正确的HTML。
- 然后,使用HTML作为输入,使用格式正确的HTML生成PDF。
- 我们会看到创建了一个BaseUri,然后将其传递给builder方法。withW3cDocument(doc,baseUri);这样,程序就知道如何针对此bseUri解析相对路径。
- 使用useFont方法,还通过将绝对路径传递到下载字体文件的位置来添加一种字体。
生成的PDF
编写自定义解析器
我们还可以插入自己的自定义解析器,该解析器可用于解析相对URI,私有地址空间中的URI甚至拒绝URI。自定义解析器需要实现FSUriResolver接口。
import java.net.URI; import java.net.URISyntaxException; import com.openhtmltopdf.extend.FSUriResolver; import com.openhtmltopdf.swing.NaiveUserAgent; public class MyResolver implements FSUriResolver { final NaiveUserAgent.DefaultUriResolver defaultUriResolver = new NaiveUserAgent.DefaultUriResolver(); @Override public String resolveURI(String baseUri, String uri) { System.out.println("URI--- " + uri); String supResolved = defaultUriResolver.resolveURI(baseUri, uri); if (supResolved == null || supResolved.isEmpty()) return null; try { URI uriObj = new URI(supResolved); //System.out.println("resolveURI..." + uriObj.toString()); return uriObj.toString(); }catch (URISyntaxException e) { e.printStackTrace(); } return null; } }
我们可以通过如下设置来使用此自定义解析器:
builder.useUriResolver(new MyResolver());