使用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());

