热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

phphtml转pdf简书,关于wkhtmltopdf,你一定想知道这些

前言如果你有Markdown或者HTML转到PDF的需求,有非常大的可能你选了一圈方案,最后找到了大名鼎鼎的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 在分页处如下的效果

768a45c10ad9

表头重复, 字体重叠

很明显可以看到表头重复出现了. 其实实际的问题不止如此, 如果单元格很宽导致换行, 很大概率会和重复显示的表头重叠.

我翻看了不下100个网页, 花费了大量时间最终找到了解决方案

thead {

display: table-row-group;

}

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

768a45c10ad9

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

有所改善, 但还是明显的发现表格的一行被切成了两部分.

下面这个就是如果你搜索这个问题最经常看到的答案了

tr {

page-break-before: always;

page-break-after: always;

page-break-inside: avoid;

}

于是, 变成了这样子

768a45c10ad9

长表格问题解决

长表格的问题到此解决.

宽表格

同样我将 markdown 文件和 HTML 文件放在了 github 上.

不加特殊处理, 得到的表格将是这样的

768a45c10ad9

表格右侧被截断

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

table {

word-wrap: break-word;

}

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

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

table td {

word-break: break-all;

}

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

其他选项

提到 wkhtmltopdf 的选项也真是让人头疼, 我本来是用了snappy和它推荐的二进制包, 所有东西都准备好了, 一个问题一直解决不了: 我已经安装了宋体, PDF 的正文中的宋体也可以正常显示了, 但唯独 header/footer 里面的中文字体死活都出不来. 因为我的需求是要有页眉和页脚, 当然也要有相应的 header-line和footer-line, 如果用HTML 来填充 header, 那么 header-line 就会消失, 这时如果用 html 中的


来代替, 又会看起来很奇怪, 后来发现直接调用二进制文件加上相应的选项在相同的机器上可以得出我需要的结果, 那么问题就很清楚了, 问题出在这个 snappy 上, 于是我一气之下直接用 PHP 的shell_exec简单封装了一下 wkhtmltopdf, 简直不能更好用, 所有问题迎刃而解.

总结

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



推荐阅读
  • 七款高效编辑器与笔记工具推荐:KindEditor自动换行功能解析
    本文推荐了七款高效的编辑器与笔记工具,并详细解析了KindEditor的自动换行功能。其中,轻笔记QingBiJi是一款完全免费的记事本软件,用户可以通过其简洁的界面和强大的功能轻松记录和管理日常事务。此外,该软件还支持多平台同步,确保用户在不同设备间无缝切换。 ... [详细]
  • 如何在Mac上构建高效的本地服务器环境
    在Mac上构建高效的本地服务器环境,首先需要了解基本步骤:1. 配置目录基础;2. 启动Apache服务;3. 添加自定义文档至本地服务器;4. 查看自定义效果。此外,还可以通过手机或其他电脑访问本机服务器,以确保跨设备的兼容性和调试效果。Mac系统自带的Apache服务为本地开发提供了便捷的工具,本文将详细介绍每个步骤的具体操作方法。 ... [详细]
  • 浏览器作为我们日常不可或缺的软件工具,其背后的运作机制却鲜为人知。本文将深入探讨浏览器内核及其版本的演变历程,帮助读者更好地理解这一关键技术组件,揭示其内部运作的奥秘。 ... [详细]
  • 在Eclipse中提升开发效率,推荐使用Google V8插件以增强Node.js的调试体验。安装方法有两种:一是通过Eclipse Marketplace搜索并安装;二是通过“Help”菜单中的“Install New Software”,在名称栏输入“googleV8”。此插件能够显著改善调试过程中的性能和响应速度,提高开发者的生产力。 ... [详细]
  • 技术日志:使用 Ruby 爬虫抓取拉勾网职位数据并生成词云分析报告
    技术日志:使用 Ruby 爬虫抓取拉勾网职位数据并生成词云分析报告 ... [详细]
  • 如何在PHP中获取数组中特定元素的索引位置
    在PHP中获取数组中特定元素的索引位置有多种方法。首先,可以使用 `array_search()` 函数,其语法为 `array_search(目标值, $array)`,该函数将返回匹配元素的第一个键名(即下标)。其次,也可以利用 `array_keys()` 函数,通过 `array_keys($array, 目标值)` 语法来获取所有匹配元素的键名列表。这两种方法都能有效解决数组元素定位的问题,具体选择取决于实际需求和性能考虑。 ... [详细]
  • 技术分享:使用 Flask、AngularJS 和 Jinja2 构建高效前后端交互系统
    技术分享:使用 Flask、AngularJS 和 Jinja2 构建高效前后端交互系统 ... [详细]
  • Vim 编辑器功能强大,但其默认的配色方案往往不尽如人意,尤其是注释颜色为蓝色时,对眼睛极为不友好。为了提升编程体验,自定义配色方案显得尤为重要。通过合理调整颜色,不仅可以减轻视觉疲劳,还能显著提高编码效率和兴趣。 ... [详细]
  • Webdriver中元素定位的多种技术与策略
    在Webdriver中,元素定位是自动化测试的关键环节。本文详细介绍了8种常用的元素定位技术与策略,包括ID、名称、标签名、类名、链接文本、部分链接文本、XPath和CSS选择器。每种方法都有其独特的优势和适用场景,通过合理选择和组合使用,可以显著提高测试脚本的稳定性和效率。此外,文章还探讨了在复杂页面结构中如何灵活运用这些定位技术,以应对各种挑战。 ... [详细]
  • 该大学网站采用PHP和MySQL技术,在校内可免费访问某些外部收费资料数据库。为了方便学生校外访问,建议通过学校账号登录实现免费访问。具体方案可包括利用学校服务器作为代理,结合身份验证机制,确保合法用户在校外也能享受免费资源。 ... [详细]
  • Python 伦理黑客技术:深入探讨后门攻击(第三部分)
    在《Python 伦理黑客技术:深入探讨后门攻击(第三部分)》中,作者详细分析了后门攻击中的Socket问题。由于TCP协议基于流,难以确定消息批次的结束点,这给后门攻击的实现带来了挑战。为了解决这一问题,文章提出了一系列有效的技术方案,包括使用特定的分隔符和长度前缀,以确保数据包的准确传输和解析。这些方法不仅提高了攻击的隐蔽性和可靠性,还为安全研究人员提供了宝贵的参考。 ... [详细]
  • 在PHP中实现腾讯云接口签名,以完成人脸核身功能的对接与签名配置时,需要注意将文档中的POST请求改为GET请求。具体步骤包括:使用你的`secretKey`生成签名字符串`$srcStr`,格式为`GET faceid.tencentcloudapi.com?`,确保参数正确拼接,避免因请求方法错误导致的签名问题。此外,还需关注API的其他参数要求,确保请求的完整性和安全性。 ... [详细]
  • 单链表的高效遍历及性能优化策略
    本文探讨了单链表的高效遍历方法及其性能优化策略。在单链表的数据结构中,插入操作的时间复杂度为O(n),而遍历操作的时间复杂度为O(n^2)。通过在 `LinkList.h` 和 `main.cpp` 文件中对单链表进行封装,我们实现了创建和销毁功能的优化,提高了单链表的使用效率。此外,文章还介绍了几种常见的优化技术,如缓存节点指针和批量处理,以进一步提升遍历性能。 ... [详细]
  • Java环境中Selenium Chrome驱动在大规模Web应用扩展时的性能限制分析 ... [详细]
  • 如何高效利用Hackbar插件提升网页调试效率
    通过合理利用Hackbar插件,可以显著提升网页调试的效率。本文介绍了如何获取并使用未包含收费功能的2.1.3版本,以确保在不升级到最新2.2.2版本的情况下,依然能够高效进行网页调试。此外,文章还提供了详细的使用技巧和常见问题解决方案,帮助开发者更好地掌握这一工具。 ... [详细]
author-avatar
皇家城市_579
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有