关于wkhtmltopdf,你一定想知道这些


- 前言
- 实践
- 长表格
- 宽表格
- 其他选项
- 总结

前言

如果你有 Markdown 或者 HTML 转到 PDF 的需求, 有非常大的可能你选了一圈方案, 最后找到了大名鼎鼎的wkhtmltopdf. 但找到它之后并没有解决所有问题, 相反, 它会带来更多的问题.
首先说一下它的优点:

  • 由于是基于 WebKit, 所以渲染结果和 Chrome( 包括其他基于 Chromium的浏览器几乎完全一致)
  • 可以和前端公用一套 CSS 样式, 结果还是体验的一致性
  • 支持大量的定制, 包括页头页脚, 页码, 目录等等, 后面会详细说

再来说一下缺点:

  • 对特别长的表格支持有问题. 其实原因还是来自 WebKit 引擎, 因为WebKit本身是用来渲染网页的, 而网页是不需要上下分页的, 所以引擎本身并不支持表格跨页显示, 需要做一些特殊处理, 划重点了.
  • 对于特别宽的表格, 如果不做处理, 它会被横向截断,同时会在表格下方出现一个 scrollbar, 但尴尬的是这个 scrollbar 不能拖动, 因此也就无法解决完整显示的问题.

所以, 优点很明显, 缺点也很明显. 而且通常如果你有需求生成 PDF, 那多数情况下是有表格的, 不解决这个问题, 这个方案就无法实施。

实践

下面让我们通过实验一步步解决上面的两个大问题.

长表格

这里我简单写了一长段表格, 然后用 MacDown 编辑器把它导出为 html, 这里只是用来说明问题, 所以就没有用我实际在生产环境使用的 Parsedown.写着写着觉得还是用代码能说的更清晰一些,
原始 markdown 文件和 html 文件就不贴在这里了, 可以查看phpwkhtmltopdf.

在 article 目录里执行
wkhtmltopdf longtable.html longtable-01.pdf

生成的 PDF 在分页处如下的效果


表头重复, 字体重叠

很明显可以看到表头重复出现了. 其实实际的问题不止如此, 如果单元格很宽导致换行, 很大概率会和重复显示的表头重叠.
我翻看了不下100个网页, 花费了大量时间最终找到了解决方案

thead {
    display: table-row-group;
}

解决了表头重复和文字重叠的问题.


表头不重复, 字体不重叠, 但一行被分割

有所改善, 但还是明显的发现表格的一行被切成了两部分.
下面这个就是如果你搜索这个问题最经常看到的答案了

tr {
    page-break-before: always;
    page-break-after: always;
    page-break-inside: avoid;
}

于是, 变成了这样子


长表格问题解决

长表格的问题到此解决.

宽表格

同样我将 markdown 文件和 HTML 文件放在了 github 上.
不加特殊处理, 得到的表格将是这样的


表格右侧被截断

这是因为默认的样式中并没有

table {
    word-wrap: break-word;
}

的设置. 我这里的例子举的有些不合理, 因为不会全是一样长的单元格宽度, 实际情况总会有长有短, 当同一列中存在一个很长的单词(或者根本不是单词, 而仅仅是很长的连起来的无意义的字符串, 像本例中那样), 该列单元格的最短列宽就会以它为准. 这样导致表格的总宽度很容易超出页面限制.

因为word-wrap 控制的是有多个单词的情况, 如果只有一个单词, 它是不做处理的. 所以需要另外加一个样式

table td {
    word-break: break-all;
}

这样的结果就是所有表格都完整的展示出来了.

其他选项

提到 wkhtmltopdf 的选项也真是让人头疼, 我本来是用了snappy和它推荐的二进制包, 所有东西都准备好了, 一个问题一直解决不了: 我已经安装了宋体, PDF 的正文中的宋体也可以正常显示了, 但唯独 header/footer 里面的中文字体死活都出不来. 因为我的需求是要有页眉和页脚, 当然也要有相应的 header-linefooter-line, 如果用HTML 来填充 header, 那么 header-line 就会消失, 这时如果用 html 中的<hr>来代替, 又会看起来很奇怪, 后来发现直接调用二进制文件加上相应的选项在相同的机器上可以得出我需要的结果, 那么问题就很清楚了, 问题出在这个 snappy 上, 于是我一气之下直接用 PHP 的shell_exec简单封装了一下 wkhtmltopdf, 简直不能更好用, 所有问题迎刃而解.

总结

宽度的问题其实在网页设计里面更常见, 我不是专业的前端, 所以对相应的样式比较陌生, 导致花了一些时间. 但分页的问题真是困扰了每个用过 wkhtmltopdf 的人, 随便一搜, 几乎全是关于这个问题, 但没有一个人真正的给出普适的真正可用的解决方案. 本文给出了我自己的一些经验, 供大家参考.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,613评论 4 59
  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,629评论 1 92
  • 春来山庄铺绿毯,篱边簇簇露凝香。 嫣红粉面随风褪,未必娇羞愧夕阳?
    晴鹤1阅读 298评论 0 5
  • 简暗,简单的阴暗。 瞥一眼便固执地迷上了。 我是一个反差较大的人,会单纯地笑的像个小孩,也会深沉得像是迟暮的老人。...
    循时阅读 384评论 0 0
  • 当年,吴绮莉不顾成龙和家人反对,一意孤行,未婚生女,威胁成龙,成龙婚内出轨吴绮莉,致其怀孕,当吴绮莉生下小龙女吴卓...
    雷人创意阅读 828评论 3 5