发布于 

java完成HTML转PDF wkhtmltopdf

为什么使用wkhtmltopdf

HTML转PDF的实现方式有很多,但是转换出来的PDF的质量又好有坏。之前试过IText和一些其他的工具,但是不是格式乱了就是由于标签书写不规范(没有结尾标签)导致转换出来的效果都不太满意,最后发现wkhtmltopdf转换格式什么基本没有问题而且使用也是比较简单就使用wkhtmltopdf。

第一步 下载安装

官网地址:https://wkhtmltopdf.org/downloads.html

根据自己的系统来选择安装包。

第二步 配置环境变量

安装完成之后找到安装路径,将其配置到环境变量中,方便使用。

配置完成环境变量之后就可以测试一下了。

看看转换效果。

可以看到转换效果是非常不错的。

第三步 代码调用wkhtmltopdf进行转换

辅助代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package fangrong.com.cn.common.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class HtmlToPdfInterceptor extends Thread {
private InputStream is;

public HtmlToPdfInterceptor(InputStream is) {
this.is = is;
}

public void run() {
try {
InputStreamReader isr = new InputStreamReader(is, "utf-8");
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line.toString()); //输出转换进度等内容
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

转换代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
package fangrong.com.cn.common.utils;


import java.io.File;

/**
* Input表单或JavaScript脚本支持:--enable-forms,下面这些是网友整理的参数说明
* wkhtmltopdf [OPTIONS]... <input file> [More input files] <output file>
* 常规选项
* --allow <path> 允许加载从指定的文件夹中的文件或文件(可重复)
* --book* 设置一会打印一本书的时候,通常设置的选项
* --collate 打印多份副本时整理
* --cookie <name> <value> 设置一个额外的cookie(可重复)
* --cookie-jar <path> 读取和写入的Cookie,并在提供的cookie jar文件
* --copies <number> 复印打印成pdf文件数(默认为1)
* --cover* <url> 使用HTML文件作为封面。它会带页眉和页脚的TOC之前插入
* --custom-header <name> <value> 设置一个附加的HTTP头(可重复)
* --debug-javascript 显示的javascript调试输出
* --default-header* 添加一个缺省的头部,与页面的左边的名称,页面数到右边,例如: --header-left '[webpage]' --header-right '[page]/[toPage]' --header-line
* --disable-external-links* 禁止生成链接到远程网页
* --disable-internal-links* 禁止使用本地链接
* --disable-javascript 禁止让网页执行JavaScript
* --disable-pdf-compression* 禁止在PDF对象使用无损压缩
* --disable-smart-shrinking* 禁止使用WebKit的智能战略收缩,使像素/ DPI比没有不变
* --disallow-local-file-access 禁止允许转换的本地文件读取其他本地文件,除非explecitily允许用 --allow
* --dpi <dpi> 显式更改DPI(这对基于X11的系统没有任何影响)
* --enable-plugins 启用已安装的插件(如Flash
* --encoding <encoding> 设置默认的文字编码
* --extended-help 显示更广泛的帮助,详细介绍了不常见的命令开关
* --forms* 打开HTML表单字段转换为PDF表单域
* --grayscale PDF格式将在灰阶产生
* --help Display help
* --htmldoc 输出程序HTML帮助
* --ignore-load-errors 忽略claimes加载过程中已经遇到了一个错误页面
* --lowquality 产生低品质的PDF/ PS。有用缩小结果文档的空间
* --manpage 输出程序手册页
* --margin-bottom <unitreal> 设置页面下边距 (default 10mm)
* --margin-left <unitreal> 将左边页边距 (default 10mm)
* --margin-right <unitreal> 设置页面右边距 (default 10mm)
* --margin-top <unitreal> 设置页面上边距 (default 10mm)
* --minimum-font-size <)
* --no-background 不打印背景
* --orientation <orientation> 设置方向为横向或纵向
* --page-height <unitreal> 页面高度 (default unit millimeter)
* --page-offset* <offset> 设置起始页码 (default )
* --page-size <size> 设置纸张大小: A4, Letter, etc.
* --page-width <unitreal> 页面宽度 (default unit millimeter)
* --password <password> HTTP验证密码
* --post <name> <value> Add an additional post field (repeatable)
* --post-file <name> <path> Post an aditional file (repeatable)
* --print-media-type* 使用的打印介质类型,而不是屏幕
* --proxy <proxy> 使用代理
* --quiet Be less verbose
* --read-args-from-stdin 读取标准输入的命令行参数
* --readme 输出程序自述
* --redirect-delay <msec> 等待几毫秒为JS-重定向(default )
* --replace* <name> <value> 替换名称,值的页眉和页脚(可重复)
* --stop-slow-scripts 停止运行缓慢的JavaScripts
* --title <text> 生成的PDF文件的标题(第一个文档的标题使用,如果没有指定)
* --toc* 插入的内容的表中的文件的开头
* --use-xserver* 使用X服务器(一些插件和其他的东西没有X11可能无法正常工作)
* --user-style-sheet <url> 指定用户的样式表,加载在每一页中
* --username <username> HTTP认证的用户名
* --version 输出版本信息退出
* --zoom <)
* <p>
* 页眉和页脚选项
* --header-center* <text> (设置在中心位置的页眉内容)
* --header-font-name* <name> (default Arial)(设置页眉的字体名称)
* --header-font-size* <size> (设置页眉的字体大小)
* --header-html* <url> (添加一个HTML页眉,后面是网址)
* --header-left* <text> (左对齐的页眉文本)
* --header-line* (显示一条线在页眉下)
* --header-right* <text> (右对齐页眉文本)
* --header-spacing* <real> (设置页眉和内容的距离,默认0)
* --footer-center* <text> (设置在中心位置的页脚内容)
* --footer-font-name* <name> (设置页脚的字体名称)
* --footer-font-size* <size> (设置页脚的字体大小default )
* --footer-html* <url> (添加一个HTML页脚,后面是网址)
* --footer-left* <text> (左对齐的页脚文本)
* --footer-line* 显示一条线在页脚内容上)
* --footer-right* <text> (右对齐页脚文本)
* --footer-spacing* <real> (设置页脚和内容的距离)
* <p>
* 页脚和页眉
* [page] 由当前正在打印的页的数目代替
* [frompage] 由要打印的第一页的数量取代
* [topage] 由最后一页要打印的数量取代
* [webpage] 通过正在打印的页面的URL替换
* [section] 由当前节的名称替换
* [subsection] 由当前小节的名称替换
* [date] 由当前日期系统的本地格式取代
* [time] 由当前时间,系统的本地格式取代
* <p>
* 轮廓选项
* --dump-outline <file> 转储目录到一个文件
* --outline 显示目录(文章中h1,h2来定)
* --outline-depth <level> 设置目录的深度(默认为4)
* <p>
* 表内容选项中
* --toc-depth* <level> Set the depth of the toc (default)
* --toc-disable-back-links* Do not link from section header to toc
* --toc-disable-links* Do not link from toc to sections
* --toc-font-name* <name> Set the font used for the toc (default Arial)
* --toc-header-font-name* <name> The font of the toc header (if unset use --toc-font-name)
* --toc-header-font-size* <size> The font size of the toc header (default)
* --toc-header-text* <text> The header text of the toc (default Table Of Contents)
* --toc-l1-font-size* <size> Set the font size on level of the toc (default)
* --toc-l1-indentation* <num> Set indentation on level of the toc (default)
* --toc-l2-font-size* <size> Set the font size on level of the toc (default)
* --toc-l2-indentation* <num> Set indentation on level of the toc (default)
* --toc-l3-font-size* <size> Set the font size on level of the toc (default)
* --toc-l3-indentation* <num> Set indentation on level of the toc (default)
* --toc-l4-font-size* <size> Set the font size on level of the toc (default)
* --toc-l4-indentation* <num> Set indentation on level of the toc (default)
* --toc-l5-font-size* <size> Set the font size on level of the toc (default)
* --toc-l5-indentation* <num> Set indentation on level of the toc (default)
* --toc-l6-font-size* <size> Set the font size on level of the toc (default)
* --toc-l6-indentation* <num> Set indentation on level of the toc (default)
* --toc-l7-font-size* <size> Set the font size on level of the toc (default)
* --toc-l7-indentation* <num> Set indentation on level of the toc (default)
* --toc-no-dots* Do not use dots, in the toc
* ------------------------------------------------------------------------------------------------------------
*/
public class HtmlToPdf {

/**
* html转pdf
*
* @param srcPath html路径,可以是硬盘上的路径,也可以是网络路径
* @param file pdf文件
* @return 转换成功返回true
*/
public static boolean convert(String srcPath, File file) {

File parent = file.getParentFile();
// 如果pdf保存路径不存在,则创建路径
if (!parent.exists()) {
parent.mkdirs();
}
StringBuilder cmd = new StringBuilder();
String toPdfTool;
if (System.getProperty("os.name").indexOf("Windows") == -1) { // 根据系统
// 非windows 系统
toPdfTool = "/usr/local/bin/wkhtmltopdf";
} else {
toPdfTool = "D:/htmlTopdf/wkhtmltopdf/bin/wkhtmltopdf.exe";
}
// 这里可以拼接页眉页脚等参数 参数详情在上方
cmd.append(toPdfTool);
cmd.append(" ");
cmd.append(srcPath);
cmd.append(" ");
cmd.append(file.getAbsolutePath());

boolean result = true;
try {
Process proc = Runtime.getRuntime().exec(cmd.toString());
HtmlToPdfInterceptor error = new HtmlToPdfInterceptor(proc.getErrorStream());
HtmlToPdfInterceptor output = new HtmlToPdfInterceptor(proc.getInputStream());
error.start();
output.start();
proc.waitFor();
} catch (Exception e) {
result = false;
e.printStackTrace();
}
return result;
}
}

到此集成完成。

使用过程中碰到的的一些坑

这些坑主要是出现在Linux环境下的

  • 乱码问题

一般乱码的主要原因就是因为Linux中没有simsun的字体,将C:\Windows\Fonts中的simsun.ttc拷贝到linux服务器/usr/share/fonts/目录下,下次再生成pdf就正常了

  • Docker容器中的java程序无法调用到Linux本地的wkhtmltopdf脚本

需要将本地的文件挂载映射到dockers容器当中


本站由 @binvv 使用 Stellar 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。