博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Docker快速验证HTML导出PDF高效方案
阅读量:5895 次
发布时间:2019-06-19

本文共 9023 字,大约阅读时间需要 30 分钟。

  hot3.png

Docker快速验证HTML导出PDF高效方案

[TOC]

需求分析

项目中用到了Echarts,想要把图文混排,当然包括echarts生成的Canvas图也导出PDF。

设计和实现时,分析了POI、iText、freemaker、world的xml模版、Jquery-printArea.js、JQuery Plugin-TableExport、flying saucer等等技术组合,不尽人意。甚至因为echarts不支持后端调用导出图片(没有简单易行的办法),一度考虑要在导出时用JfreeCharts重新画一遍图表。一是不能完整体现原有设计样式,二是工期不支持这么庞大的工作量(硬撸代码解析html生成word或pdf。好吧,也同时觉得挺low的);

最终选择了wkhtmltopdf,实现了预期目标。整理成笔记,分享给大家。同时,发现docker hub有wkhtmltopdf基于apline搭建的web service镜像,生产环境可以上Docker的同学有福了,这应该是个更加高效的方案。后续考虑整合到支撑平台中,一并开源出来。

笔记本实验

本地测试为Mac Book,生产环境请自行评估调整。

下载和安装

B4下,brew仓库里居然没有,所以 brew install wkhtmltopdf安装报错。

直接贴官方了:有依赖亲自行安装依赖;

验证

ChinaDreams:workspace kangcunhua$ wkhtmltopdf --versionwkhtmltopdf 0.12.4 (with patched qt)

测试

wkhtmltopdf  --zoom 4 toc --toc-header-text "第四季度季报" index.html export.pdf

模拟商业环境

我们拿到项目中实践验证下方案。商业项目,往往是残酷的要求,会遇到各种各样demo时碰不上的挑战。

思路还是先用docker神器,模拟商业环境,验证方案,然后再修订验证后的方案到正式项目环境验证。

客户方提供的环境是SuSE。我们先来看看是哪个版本

cat /etc/SuSE-release # 可以看到补丁版本SUSE LINUX Enterprise Server 11 (x86_64)VERSION = 11PATCHLEVEL = 4

请Docker神器

查找SuSE镜像,恰好有一个11版本的,下载镜像先

$ docker search SUSE # yuzhenpin/suse-11-sp3-x86_64-java$ docker pull yuzhenpin/suse-11-sp3-x86_64-java

启动镜像

docker run --name suse-ep -it yuzhenpin/suse-11-sp3-x86_64-java /bin/bash9e023776a1d5:/ # java -versionjava version "1.7.0_51"Java(TM) SE Runtime Environment (build 1.7.0_51-b13)Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)9e023776a1d5:/ # id uid=0(root) gid=0(root) groups=0(root)9e023776a1d5:/ # groupadd prms && useradd -d /prms -g prms -m prms9e023776a1d5:/ # passwd prms9e023776a1d5:/ # su prms

安装和配置

因为下载的二进制版本的,直接把wkhtmltopdf拷贝进容器即可。index.html是写的测试页面,后文附有源码:此文件用到的jquery相关js直接引用了CDN,故实验在联网环境下进行的。

ChinaDreams:copy2docker kangcunhua$ docker cp wkhtmltox-0.12.4_linux-generic-amd64.tar.xz su-ext:/prms/workspaceChinaDreams:copy2docker kangcunhua$ docker cp index.html su-ext:/prms/workspace

检查运行依赖

使用ldd命令,not found的就是对应的依赖包不存在:

7d183ecb0026:/prms/workspace/wkhtmltox/bin # ldd wkhtmltopdf 	linux-vdso.so.1 =>  (0x00007ffe40bd2000)	libXrender.so.1 => not found	libfontconfig.so.1 => not found	libfreetype.so.6 => not found	libXext.so.6 => not found	libX11.so.6 => not found	libz.so.1 => /lib64/libz.so.1 (0x00007f9ca59ad000)	libdl.so.2 => /lib64/libdl.so.2 (0x00007f9ca57a9000)	librt.so.1 => /lib64/librt.so.1 (0x00007f9ca55a0000)	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f9ca5383000)	libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007f9ca507b000)	libm.so.6 => /lib64/libm.so.6 (0x00007f9ca4e02000)	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f9ca4bec000)	libc.so.6 => /lib64/libc.so.6 (0x00007f9ca4870000)	/lib64/ld-linux-x86-64.so.2 (0x00007f9ca5bc5000)

安装依赖

使用 zypper se 命令查找,根据查找结果,来安装需要的版本;

7d183ecb0026:/prms/workspace/wkhtmltox/bin # zypper se libXrender                                                                       7d183ecb0026:/prms/workspace/wkhtmltox/bin # zypper install xorg-x11-libXrender7d183ecb0026:/prms/workspace/wkhtmltox/bin # zypper se libfreetype     7d183ecb0026:/prms/workspace/wkhtmltox/bin # zypper install libfreetype67d183ecb0026:/prms/workspace/wkhtmltox/bin # zypper se libXext7d183ecb0026:/prms/workspace/wkhtmltox/bin # zypper install xorg-x11-libXext7d183ecb0026:/prms/workspace/wkhtmltox/bin # zypper se fontconfig7d183ecb0026:/prms/workspace/wkhtmltox/bin # zypper install fontconfig7d183ecb0026:/prms/workspace/wkhtmltox/bin # zypper se libX117d183ecb0026:/prms/workspace/wkhtmltox/bin # zypper install xorg-x11-libX11

需要在html代码中指定font-face,所以需要一种支持中英文的字体。这里不指定的话,中英文都是黑色方框。因为不知容器使用的是何种字体,没找到Suse如何查看当前已有字体。从网下下载了文泉驿正黑,cp了字体进来,发现是乱码,mv重命名为tt.tff;cp到字体目录。

7d183ecb0026:/usr/share/fonts # mkdir windows7d183ecb0026:/prms/workspace # mv tt.ttf /usr/share/fonts/windows/7d183ecb0026:/prms/workspace # ./wkhtmltox/bin/wkhtmltopdf index.html exp.pdfQIconvCodec::convertToUnicode: using Latin-1 for conversion, iconv_open failedQIconvCodec::convertFromUnicode: using Latin-1 for conversion, iconv_open failedLoading pages (1/6)Counting pages (2/6)                                               Resolving links (4/6)                                                       Loading headers and footers (5/6)                                           Printing pages (6/6)Done

和容器之间复制文件

ChinaDreams:copy2docker kangcunhua$ docker cp wkhtmltox-0.12.4_linux-generic-amd64.tar.xz su-ext:/prms/workspaceChinaDreams:copy2docker kangcunhua$ docker cp index.html su-ext:/prms/workspaceChinaDreams:copy2docker kangcunhua$ docker cp 文泉驿等宽正黑.ttf su-ext:/prms/workspaceChinaDreams:copy2docker kangcunhua$ docker cp su-ext:/prms/workspace/exp.pdf .

商业环境实战

待补充。

2017.11.10update: 商业环境最大的挑战是内网。还有个挑战是客户使用的是SuSE Enterprise,这种情况下,如果缺少依赖,补丁包安装很麻烦。

通过走手续,在内网申请了wkhtmltopdf二进制包,工程师传到测试环境,直接运行了测试命令,居然一条就过!依赖不缺,甚至中文字体也不缺。这只能说是运气。不过,凡事预则立,多准备一些,事情周密一些总是没错的。

接下来,就是撰写个工具类调用shell命令了,可能还要考虑权限认证的问题。不过,从前台登录后的UI发起导出,应该不会存在需要认证的问题。

皆大欢喜!

错误、参考和源码

报错:SslHandshakeFailedError

笔记本实验时,报了个错。貌似也不影响最终需要的导出PDF结果。后来猜测应该是页面上有button或与打印无关的js导致的,删了就好了。国外的网友写了一个工具/moodle-scraper,也碰上了这个问题:这个错误貌似不是我第一个碰上,官方也没有修复。

moodle-scraper的KNOWN CURRENT ISSUES

WebToPDFKNOWN CURRENT ISSUES:1) "Issue found on page:wkhtmltopdf reported an error:Mon Mar 28 20:51:52 unreg-30-152.dyn.carleton.edu wkhtmltopdf[3817] 
: CGContextSetShouldAntialias: invalid context 0x0" As of Spring 2016 this problem has not been solved and seems to be a problem with whtmltopdf using a deprecated library of Mac OSX. Try it with Windows and see if it breaks?Additionally, reported issue on GitHub: https://github.com/wkhtmltopdf/wkhtmltopdf/issues/2196

报错信息:

Loading pages (1/6)^C===========================>                               ] 48%ChinaDreams:WebRoot kangcunhua$ wkhtmltopdf --disable-smart-shrinking index.html export.pdfLoading pages (1/6)QFont::setPixelSize: Pixel size <= 0 (0)                     ] 49%Counting pages (2/6)                                               QFont::setPixelSize: Pixel size <= 0 (0)=====================] Object 1 of 1Resolving links (4/6)                                                       Loading headers and footers (5/6)                                           Printing pages (6/6)Nov  7 13:53:25  wkhtmltopdf[2603] 
: CGContextSetShouldAntialias: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.Nov 7 13:53:25 wkhtmltopdf[2603]
: CGContextSetShouldSmoothFonts: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.Nov 7 13:53:25 wkhtmltopdf[2603]
: CGContextSetFillColorSpace: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.Nov 7 13:53:25 wkhtmltopdf[2603]
: CGContextSetFillColor: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.Done Exit with code 1 due to network error: SslHandshakeFailedError

报错convertToUnicode:

在容器中,配置好之后,运行转换命令,报了一个错误,但从结果来看,不影响最终pdf生产。故此处没有特殊处理,不过网友给出了解决方案:强迫症或时间充分的网友可以自行验证和修复:

7d183ecb0026:/prms/workspace # ./wkhtmltox/bin/wkhtmltopdf index.html exp.pdfQIconvCodec::convertToUnicode: using Latin-1 for conversion, iconv_open failedQIconvCodec::convertFromUnicode: using Latin-1 for conversion, iconv_open failedLoading pages (1/6)Counting pages (2/6)                                               Resolving links (4/6)                                                       Loading headers and footers (5/6)                                           Printing pages (6/6)Done

注意上文报了一个Qt错误,

QIconvCodec::convertToUnicode: using Latin-1 for conversion, iconv_open failedQIconvCodec::convertFromUnicode: using Latin-1 for conversion, iconv_open failed

这是个:

下载

./configure -prefix=$PWD/_install -host=arm-linux-gnueabihf   make  make install

把_install/lib 下的preloadable_libiconv.so 拷到系统的/system/lib 下,

export LD_PRELOAD=/system/lib/preloadable_libiconv.so

参考链接1

感谢各位勇于分享的亲:

    • 这篇附有C#源码,直接转换table的html代码为word的xml格式,我一开始最想解决的办法,可惜没有Java版的。自己硬撸又来不及;最终放弃。
    • wkhtmltopdf 有个很好的方法,就是在那个div的样式后添加一个:page-break-inside:avoid;就ok了。
    • 这篇文章直接指出了wkhtml支持echarts的canvas标签,哇哈哈:)
    • html的table中不能用thead,用了后换页会出现两个表头问题如图
    • 可以用thead,不过得加样式 tr { page-break-inside: avoid !important;}
    • php扩展php-wkhtmltox项目主页:

参考链接2

静态页面

      
My JSP 'index.jsp' starting page

First Title

测试:test

by kang.cunhua;

二级标题

		正文:		轻轻的我走了,		正如我轻轻的来;		我轻轻的招手,		作别西天的云彩。		----				那河畔的金柳,		是夕阳中的新娘;		波光里的艳影,		在我的心头荡漾。				----				软泥上的青荇⑴,		油油的在水底招摇⑵;		在康河的柔波里,		我甘心做一条水草!				----				那榆荫下的一潭,		不是清泉,是天上虹;		揉碎在浮藻间,		沉淀着彩虹似的梦。				

三级标题

第一行第一列 第一行第一列 第一行第一列 第一行第一列
第一行第一列 第一行第一列 第一行第一列 第一行第一列 第一行第一列
第一行第一列 第一行第一列 第一行第一列 第一行第一列 第一行第一列

四级标题

转载于:https://my.oschina.net/hexie/blog/1591687

你可能感兴趣的文章
扩展 DbUtility (1)
查看>>
iOS开发UI篇—使用picker View控件完成一个简单的选餐应用
查看>>
使用UITableView实现图片视差效果
查看>>
CentOS RHEL 安装 Tomcat 7
查看>>
erlang如何有效地监视大量的并发连接
查看>>
Windows下Mysql5.6启用监控执行脚本的日志
查看>>
Apple Developer Registration and DUNS Number Not Accepted
查看>>
motion移植
查看>>
Hadoop学习笔记系列文章导航
查看>>
转一贴,今天实在写累了,也看累了--【Python异步非阻塞IO多路复用Select/Poll/Epoll使用】...
查看>>
四川大学线下编程比赛第一题:数字填充
查看>>
Codeforces Round #290 (Div. 2) C. Fox And Names dfs
查看>>
iOS开发-NSOperation与GCD区别
查看>>
扩展方法使用
查看>>
Win7 64位 php-5.5.13+Apache 2.4.9+mysql-5.6.19 配置
查看>>
HOJ 2245 浮游三角胞(数学啊 )
查看>>
spring mvc 和ajax异步交互完整实例
查看>>
不同页面之间实现参数传递的几种方式讨论
查看>>
程序员进阶之路—如何独当一面
查看>>
SpringMVC中ModelAndView addObject()设置的值jsp取不到的问题
查看>>