Introduction

Intro

在日常开发中, 出于某些特殊的需求, 需要在服务器上(centos/ubuntu)上将H5页面转换为
其他可读或者可打印的文件, 例如pdf, image, 此时则需要相应的软件进行此类转换工作.
类似的应用, 有:htmltoimages, htmltopdf, 此文章主要讲解htmltopdf的安装和使用,
其他类似的应用的相关环境配置大体相同.

Glossary

  • 文档对象: PDF文档中的文档对象,共有三种类型的”文档对象”, 他们分别是”页面对象”, “封面对象”和”目录对象”
  • 页面对象: 以页面的形式在PDF文档中呈现的对象, 相对于封面对象和目录对象而言, 一般为PDF中内容
  • 封面对象: 以封面的形式在PDF文档中呈现的对象
  • 目录对象: 以目录的形式在PDF文档中呈现的对象, TOC对象
  • 大纲: 阅读PDF文档时的书签导航
  • 外链: 所有在这个页面中且不指向它自身页面中锚点的超链接
  • 内链: 在这个页面中且指向的目标页面是这个页面本身中的一个锚点的超链接

wkhtmltopdf能够把多个”对象”合并生成一个pdf文档, 通过组装各类对象(页面, 封面, 目录).其他命令格式为
wkhtmltopdf [GLOBAL OPTION]... [OBJECT]... <output file>.

页面对象将一个网页作为内容输出到pdf中, 页面对象的参数可以放在’全局参数域’或者’页面参数域’中,
WK会根据实际情况寻找参数并应用到页眉, 页脚, 页面. 页面对象的命令格式:
(page)? <input url/file name> [PAGE OPTION]..., 其中page作为默认值, 一般不指定.

封面对象把一个网页作为封面输出到PDF文档中, 不包含页眉, 页脚, 格式为:
cover <input url/file name> [PAGE OPTION]..., 注意需要指定cover.

目录对象输出一个目录到PDF文件中, 命令格式:
toc [TOC OPTION]...

参考: wkhtmltopdf简介

Font

Add

对于centos或者ubuntu, 由于对桌面化的支持程度不足, 缺少中文字体库, 在使用wkhtmltopdf
进行图形化的过程中, 对英文字体和中文字体的填入会出现乱码现象, 此时需要下载对应的
字体库, 并将字体库加载到系统字体库中.

下载SimSun, 微软雅黑
字体库到系统中,将字体库拷贝到字体库存放路径下面, 其中Linux的字体库存放路径以及字体库配置见:

1
2
3
4
5
6
7
8
9
# 系统字体库
/usr/share/fonts
# 用户字体库
~/.local/share/fonts

# 系统字体库配置文件
/etc/fonts/fonts.conf
# 用户字体库配置文件
~/.fonts.conf

在拷贝字体库到相应路径下之后, 还需要将字体加载到系统中, 否则无法立即生效:

1
2
3
4
5
6
# centos系统需要额外的生成字体的索引信息, 并创建相应目录
mkfontscale
mkfontdir

# 刷新字体
sudo fc-cache -fv

Show

显示当前的所有字体里列表, 有两个命令:

1
2
3
4
5
# 查看当前的所有字体
fc-list

# 显示所有字体的描述信息
fc-match -s

其中后者的输出例子如下:

1
2
3
4
5
6
7
8
# 字体库文件---字体名称---字体的style(斜体, 粗体等等)
SimSun.ttf: "SimSun" "Regular"
cursor.pfa: "Cursor" "Regular"
Microsoft-Yahei.ttf: "Microsoft YaHei" "Normal"
STIX-Regular.otf: "STIX" "Regular"
STIX-Bold.otf: "STIX" "Bold"
STIX-Italic.otf: "STIX" "Italic"
STIX-BoldItalic.otf: "STIX" "Bold Italic"

之后, 可以查看某一个字体的详细信息, 确定file/family是否一致:

1
2
3
4
5
# 匹配中文环境中monospace的斜体, 并且仅仅显示字体名
fc-match monospace:lang=zh:slant=italic family

# 查看微软雅黑的详细信息
fc-match -v "Microsoft Yahei"

之后, 就可在系统的其他应用中指定”微软雅黑”字体来使用了.

参考:ubuntu-fonts

Set

这里列出常见的字体family值, 以便后续的使用.

字体中文名 family
宋体 SimSun
黑体 SimHei
微软雅黑 Microsoft YaHei
微软正黑 Microsoft JhengHei
新宋体 NSimSun
仿宋 FangSong
楷体 KaiTi
:—-: :—-:
华文细黑 STHeiti Light
华文黑体 STHeiti

Install

仅支持0.12.4, 不支持0.13

Centos

在centos上安装wkhtmltopdf, 首先下载wkhtmltopdf的rpm包,
进入官网下载相应版本的包.

1
2
3
4
5
6
# 安装图形化支持软件
yum install -y libpng, libjpeg, openssl, icu, libX11, libXext, libXrender
yum install -y xorg-x11-fonts-Type1, xorg-x11-fonts-75dpi

# 安装URW字体, 支持英文的图形化输出
yum install urw-fonts

安装wkhtmlpdf应用(推荐):

1
2
3
4
5
6
7
8
9
10
11
# 下载编译完成的源码包
wget http://download.gna.org/wkhtmltopdf/0.12/0.12.4/wkhtmltox-0.12.4_linux-generic-amd64.tar.xz
unxz wkhtmltox-0.12.4_linux-generic-amd64.tar.xz
tar -xvf wkhtmltox-0.12.4_linux-generic-amd64.tar
mv wkhtmltox/bin/* /usr/local/bin/
rm -rf wkhtmltox
rm -f wkhtmltox-0.12.4_linux-generic-amd64.tar

# 下载rpm(目前未找到相应文件)
wget http://download.gna.org/wkhtmltopdf/0.12/0.12.2/wkhtmltox-0.12.2_linux-centos7-amd64.rpm
rpm -Uvh wkhtmltox-0.12.2_linux-centos7-amd64.rpm

参考: install wkhtmltopdf on centos7

Command

根据第一节中关于文档对象, 页面对象, 封面对象, 目录对象的介绍可知, 整个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
28
29
30
31
32
    --collate             当输出多个副本时进行校验(这是默认设置)
--no-collate 当输出多个副本时不进行校验
--cookie-jar <path> 从提供的JAR文件中读写cookie数据
--copies <number> 设置输出副本的数量(默认主1),其实为1就够了
-d, --dpi <dpi> 指定一个要分辨率(这在 X11 系统中并没有什么卵用)
-H, --extended-help 相对 -h 参数,显示更详细的说明文档
-g, --grayscale 指定以灰度图生成PDF文档。占用的空间更小
-h, --help 显示帮助信息
--htmldoc 输出程序的html帮助文档
--image-dpi <integer> 当页面中有内嵌的图片时,
会下载此命令行参数指定尺寸的图片(默认值是 600)
--image-quality <interger> 当使用 jpeg 算法压缩图片时使用这个参数指定的质量(默认为 94)
--license 输出授权信息并退出
-l, --lowquality 生成低质量的 PDF/PS ,能够很好的节约最终生成文档所占存储空间
--manpage 输出程序的手册页
-B, --margin-bottom <unitreal> 设置页面的 底边距
-L, --margin-left <unitreal> 设置页面的 左边距 (默认是 10mm)
-R, --margin-right <unitreal> 设置页面的 右边距 (默认是 10mm)
-T, --margin-top <unitreal> 设置页面的 上边距
-O, --orientation <orientation> 设置为“风景(Landscape)”或“肖像(Portrait)”模式,
默认是肖像模块(Portrait)
--page-height <unitreal> 页面高度
-s, --page-size <Size> 设置页面的尺寸,如:A4,Letter等,默认是:A4
--page-width <unitreal> 页面宽度
--no-pdf-compression 不对PDF对象使用丢失少量信息的压缩算法,不建议使用些参数,
因为生成的PDF文件会非常大。
-q, --quiet 静态模式,不在标准输出中打印任何信息
--read-args-from-stdin 从标准输入中读取命令行参数,后续会有针对此指令的详细介绍,
请参见 **从标准输入获取参数**
--readme 输出程序的 readme 文档
--title <text> 生成的PDF文档的标题,如果不指定则使用第一个文档的标题
-V, --version 输出版本信息后退出

大纲参数

1
2
3
4
5
--dump-default-toc-xsl     输出默认的 TOC xsl 样式表到标准输出
--dump-outline <file> 输出“大纲”到指定的文件(文件内容为xml)
--outline 在生成的PDF文档中输出“大纲”(这是默认设置)
--no-outline 不在pdf文档中输出大纲
--outline-depth <level> 设置生成大纲的深度(默认为 4)

页面对象

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
    --allow <path>                指定加载HTML中相对路径文件的目录(可重复使用此参数指定多个
目录),这个参数会在后面进行更详细的讲解
--background 输出页面背景到PDF文档(这是默认设置)
--no-background 不输出页面背景到PDF文档
--cache-dir <path> 网页的缓存目录
--checkbox-checked-svg <path> 使用指定的SVG文件渲染选中的复选框
--checkbox-svg <path> 使用指定的SVG文件渲染未选中的筛选框
--cookie <name> <value> 设置访问网页时的cookie,value 需要进行url编码
(可重复使用此参数指定多个cookie)
--custom-header <name> <value> 设置访问网页时的HTTP头(可重复使用此参数指定多个HTTP头)
--custom-header-propagation 为每个要加载的资源添加由 --custom-header 指定的HTTP头
--no-custom-header-propagation 不为每个要加载的资源添加由 --custom-header 指定的HTTP头
--debug-javascript 显示javascript调试输出的信息
--no-debug-javascript 不显示javascript调试输出的信息(这是默认设置)
--default-header 添加一个默认的“头”,在页面的左头显示页面的名字,
在页面的右头显示页码,这相对于进行了如下设置:
--header-left='[webpage]'
--header-right='[page]/[toPage]'
--top 2cm
--header-line
--encoding <encoding> 为输入的文本设置默认的编码方式
--disable-external-links 禁止页面中的外链生成超链接
--enable-external-links 允许页面中的外链生成超链接(这是默认设置)
--disable-forms 不转换HTML表单为PDF表单(这是默认设置)
--enable-forms 转换HTML表单为PDF表单
--images 加载图片并输出到PDF文档(这是默认设置)
--no-images 在生成的PDF文档中过滤掉图片
--disable-internal-links 禁止页面中的内链生成超链接
--enable-internal-links 允许页面中的内链生成超连接(这是默认设置)
-n, --disable-javascript 禁止WEB页面执行 javascript
--enable-javascript 允许WEB页面执行 javascript(这是默认设置)
--javascript-delay <msec> 延迟一定的毫秒等待javascript 执行完成(默认值是200)
--load-error-handling <handler> 指定当页面加载失败后的动作,可以指定为:abort(中止)、
ignore(忽略)、skip(跳过);(默认值是:abort)
--load-media-error-handling <handler> 指定当媒体文件加载失败后的动作,可以指定为:
abort(中止)、ignore(忽略)、skip(跳过);
(默认值是:ignore)
--disable-local-file-access 不允许一个本地文件加载其他的本地文件,使用命令行参数
`--allow` 指定的目录除外。
--enable-local-file-access 允许本地文件加载其他的本地文件(这是默认设置)
--minimum-font-size <int> 设置最小的字号,除非必要不推荐使用该参数
--exclude-from-outline 拒绝加载当前页面到PDF文档的目录和大纲中
--include-in-outline 加载当前页面到PDF文档的目录和大纲中(这是默认设置)
--page-offset <offset> 设置页码的起始值(默认值为0)
--password <password> HTTP身份认证的密码
--disable-plugins 禁止使用插件(这是默认设置)
--enable-plugins 允许使用插件,但插件可能并不工作
--post <name> <value> 添加一个POST字段,可以重复使用该参数添加多个POST字段。
--post-file <name> <value> 添加一个POST文件,可以重复使用该参数添加多个文件。
--print-media-type 用显示媒体类型代替屏幕
--no-print-media-type 不用显示媒体类型代替屏幕
-p, --proxy <proxy> 使用代理
--radiobutton-checked-svg <path> 使用指定的SVG文件渲染选中的单选框
--radiobutton-svg <path> 使用指定的SVG文件渲染未选中的单选框
--run-sript <js> 页面加载完成后执行一个附加的JS文件,可以重复使用此参数指定
多个要在页面加载完成后要执行的JS文件。
--disable-smart-shrinking 不使用智能收缩策略
--enable-smart-shrinking 使用智能收缩策略(这是默认设置)
--stop-slow-scripts 停止运行缓慢的javascript代码(这是默认设置)
--no-stop-slow-scripts 不停止运行缓慢的javascript代码
--disable-toc-back-links 禁止从标题链接到目录(这是默认设置)
--enable-toc-back-links 允许从标题链接到目录
--user-style-sheet <url> 设置一个在每个页面都加载的用户自定义样式表
--username <username> HTTP身谁的用户名
--viewport-size <> 设置窗口大小,需要你自定义滚动条或css属性来自适应窗口大小。
--window-status <windowStatus> Wait until window.status is equal to
this string before rendering page
--zoom <float> 设置转换成PDF时页面的缩放比例(默认为1)

页眉页脚

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
--footer-center <text>        在页脚的居中部分显示页脚文本 <text>
--footer-font-name <name> 设置页脚的字体 (默认为 Arial)
--footer-font-size <size> 设置页脚的字体大小 (默认为 12)
--footer-html <url> 添加一个html作为页脚
--footer-left <text> 在页脚的居左部分显示页脚文本 <text>
--footer-line 在页脚上方显示一条直线分隔正文
--no-footer-line 不使用直线分隔页脚与正文(这是默认设置)
--footer-right <text> 在页脚的居右部分显示页脚文本 <text>
--footer-spacing <real> 页脚与正文之间的距离(默认为零)

--header-center <text> 在页眉的居中部分显示页眉文本 <text>
--header-font-name <name> 设置页眉的字体 (默认为 Arial)
--header-font-size <size> 设置页眉的字体大小 (默认为 12)
--header-html <url> 添加一个html作为页眉
--header-left <text> 在页眉的居左部分显示页眉文本 <text>
--header-line 在页眉下方显示一条直线分隔正文
--no-header-line 不使用直线分隔页眉与正文(这是默认设置)
--header-right <text> 在页眉的居右部分显示页眉文本 <text>
--header-spacing <real> 页眉与正文之间的距离(默认为零)

其中页眉页脚中text可以插入特殊的值, 具体说明如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
[page]       当前正在被输出页面的页码
[frompage] 第一页在文档中的页码
[topage] 最后一面在文档中的页码
[webpage] 当前正在被输出页面的URL
[section] 当前正在被输出的章节的名字
[subsection] 当前正在被输出的小节的名字
[date] 本地系统格式的当前日期
[isodate] ISO 8601 格式的当前日期
[time] 本地系统格式的当前时间
[title] 当前对象的标题
[doctitle] 输出文档的标题
[sitepage] 当前正在处理的对象中当前页面的页码
[sitepages] 当前正在处理的对象中的总页数

目录对象

1
2
3
4
5
6
--disable-dotted-lines        在目录中不使用虚线
--toc-header-text <text> 设置目录的页眉文本
--toc-level-indentation <width> 第级标题在目录中的缩进宽度(默认为1em)
--disable-toc-links 在目录中不生成指向内容锚点的超链接
--toc-text-size-shrink <real> 在目录中每级标题的缩放比例(默认为0.8)
--xsl-style-sheet <file> 使用自定义的 XSL 样式表显示目录内容

Example

Simple Test

首先确保H5页面的存在, 并下载完该H5依赖的所有其他css, js, image资源, 之后就可以执行命令:

1
2
3
wkhtmltopdf --dpi 300 --disable-javascript \
--load-error-handling ignore \
permanent.html export.pdf

这是会根据permanent.html中字体以及系统默认字体来进行pdf的生成,
具体文件测试见grocery-shop/project/docker目录.

Special Font

在html中指定微软雅黑字体, 以便将htmltopdf的时候能够使用微软字体, 在css中的设置为:

1
body { font-family: "Microsoft YaHei"; }

调用wkhtmltopdf命令:

1
2
3
4
5
6
7
8
9
10
wkhtmltopdf --dpi 500 --no-background --print-media-type --disable-smart-shrinking \
--header-spacing 3 \
--load-error-handling ignore \
--footer-left "https://ceac.state.gov/GenNIV/General/ESign/Complete_Done.aspx?node=Done" \
--footer-font-size 7 \
--footer-right "[page]/[topage]" \
--header-center "Nonimmigrant Visa - Confirmation Page" \
--header-left "[date]" \
--header-font-size 7 \
permanent_sign.html sign.pdf

media

对于某些定义了@media的H5页面, 会根据设备类型, 具体特点和环境来进行不同的样式应用,
默认情况下wkhtmltopdf不会进行此类判断, 此时需要增加参数--print-media-type来指明
需要对此类样式进行额外的操作.

参考: print-media-type

shrinking

在centos上生成pdf的时候发现某些样式会自动的收缩, 而且dpi参数无法使用, 此时需要增加
参数--disable-smart-shrinking禁用智能收缩, 以便启用dpi.

参考: disable-smart-shrinking

javascript

在某些场合可能需要--disable-javascript来确保页面的正确生成, 但是在很多页面中, 很多样式时在打印时时动态的,
需要执行javascript才能生成正确的样式, 例如如下例子:

1
2
3
4
5
6
7
8
9
10
11
<script type="text/javascript">
$(document).ready(function() {
hidePrintPreview();
});

function hidePrintPreview() {
$("#saveHeader").addClass("noPrint");
$("#saveFooter").addClass("noPrint");
$("#menubar").addClass("noPrint");
}
</script>

此时使用wkhtmltopdf就需要开启--enable-javascript选项, 当然, 这是默认值.