需求分析
項目中用到了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 --version
wkhtmltopdf 0.12.4 (with patched qt)
測試
聯網抓取
ChinaDreams:~ kangcunhua$ wkhtmltopdf --header-center '報表' --outline --header-line --margin-top 2cm --header-line http://www.qq.com/ qq.pdf
本地頁面測試
index.html見靜態頁面
–zoom 4 是Mac book上實驗出來的參數,這樣頁面是正常A4寬幅;在windows10、Suse 11下不用加這個參數。
toc 參數生成目錄,包括左側導航;—toc-header-text自定義目錄名;
ChinaDreams:~ kangcunhua$ 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 = 11
PATCHLEVEL = 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/bash
9e023776a1d5:/ # java -version
java 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 prms
9e023776a1d5:/ # passwd prms
9e023776a1d5:/ # 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/workspace
ChinaDreams: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-libXrender
7d183ecb0026:/prms/workspace/wkhtmltox/bin # zypper se libfreetype
7d183ecb0026:/prms/workspace/wkhtmltox/bin # zypper install libfreetype6
7d183ecb0026:/prms/workspace/wkhtmltox/bin # zypper se libXext
7d183ecb0026:/prms/workspace/wkhtmltox/bin # zypper install xorg-x11-libXext
7d183ecb0026:/prms/workspace/wkhtmltox/bin # zypper se fontconfig
7d183ecb0026:/prms/workspace/wkhtmltox/bin # zypper install fontconfig
7d183ecb0026:/prms/workspace/wkhtmltox/bin # zypper se libX11
7d183ecb0026:/prms/workspace/wkhtmltox/bin # zypper install xorg-x11-libX11
需要在html代碼中指定font-face,所以需要一種支持中英文的字體。這裏不指定的話,中英文都是黑色方框。因爲不知容器使用的是何種字體,沒找到Suse如何查看當前已有字體。從網下下載了文泉驛正黑,cp了字體進來,發現是亂碼,mv重命名爲tt.tff;cp到字體目錄。
7d183ecb0026:/usr/share/fonts # mkdir windows
7d183ecb0026:/prms/workspace # mv tt.ttf /usr/share/fonts/windows/
7d183ecb0026:/prms/workspace # ./wkhtmltox/bin/wkhtmltopdf index.html exp.pdf
QIconvCodec::convertToUnicode: using Latin-1 for conversion, iconv_open failed
QIconvCodec::convertFromUnicode: using Latin-1 for conversion, iconv_open failed
Loading 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/workspace
ChinaDreams:copy2docker kangcunhua$ docker cp index.html su-ext:/prms/workspace
ChinaDreams:copy2docker kangcunhua$ docker cp 文泉驛等寬正黑.ttf su-ext:/prms/workspace
ChinaDreams:copy2docker kangcunhua$ docker cp su-ext:/prms/workspace/exp.pdf .
商業環境實戰
待補充。
2017.11.10update: 商業環境最大的挑戰是內網。還有個挑戰是客戶使用的是SuSE Enterprise,這種情況下,如果缺少依賴,補丁包安裝很麻煩。
通過走手續,在內網申請了wkhtmltopdf二進制包,工程師傳到測試環境,直接運行了測試命令,居然一條就過!依賴不缺,甚至中文字體也不缺。這隻能說是運氣。不過,凡事預則立,多準備一些,事情周密一些總是沒錯的。
接下來,就是撰寫個工具類調用shell命令了,可能還要考慮權限認證的問題。不過,從前臺登錄後的UI發起導出,應該不會存在需要認證的問題。
皆大歡喜!
錯誤、參考和源碼
報錯:SslHandshakeFailedError
筆記本實驗時,報了個錯。貌似也不影響最終需要的導出PDF結果。後來猜測應該是頁面上有button或與打印無關的js導致的,刪了就好了。國外的網友寫了一個工具carleton/moodle-scraper,也碰上了這個問題:這個錯誤貌似不是我第一個碰上,官方也沒有修復。
moodle-scraper的KNOWN CURRENT ISSUES
WebToPDF
KNOWN 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] <Error>: 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.pdf
Loading pages (1/6)
QFont::setPixelSize: Pixel size <= 0 (0) ] 49%
Counting pages (2/6)
QFont::setPixelSize: Pixel size <= 0 (0)=====================] Object 1 of 1
Resolving links (4/6)
Loading headers and footers (5/6)
Printing pages (6/6)
Nov 7 13:53:25 wkhtmltopdf[2603] <Error>: 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] <Error>: 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] <Error>: 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] <Error>: 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.pdf
QIconvCodec::convertToUnicode: using Latin-1 for conversion, iconv_open failed
QIconvCodec::convertFromUnicode: using Latin-1 for conversion, iconv_open failed
Loading 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 failed
QIconvCodec::convertFromUnicode: using Latin-1 for conversion, iconv_open failed
這是個Qt移植錯誤:
> ./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
感謝各位勇於分享的親:
- jquery PrintArea 實現票據的套打功能(代碼)
- 通過選擇excel文件或輸入json數據,自動生成圖表工具
- FreeMarker + xml 導出word
- How To Convert an HTML Table into an XML File
- 這篇附有C#源碼,直接轉換table的html代碼爲word的xml格式,我一開始最想解決的辦法,可惜沒有Java版的。自己硬擼又來不及;最終放棄。
- flying saucer html轉pdf經驗分享
- 最好用Html轉pdf的工具——wkhtmltopdf
- wkhtmltopdf 參數介紹
- HTML 轉 PDF 排雷 之 wkhtmltopdf 轉換得到的PDF沒有內容
- wkhtmltopdf解決分頁問題
- wkhtmltopdf 有個很好的方法,就是在那個div的樣式後添加一個:page-break-inside:avoid;就ok了。
- iText和flying saucer結合生成pdf的技術
- web打印一篇就夠,jspdf,wkhtmltopdf
- 使用wkhtmltopdf將html轉爲pdf :
- 這篇文章直接指出了wkhtml支持echarts的canvas標籤,哇哈哈:)
- HTML轉PDF工具(wkhtmltopdf)介紹,支持widows和linux
- html的table中不能用thead,用了後換頁會出現兩個表頭問題如圖
- 可以用thead,不過得加樣式 tr { page-break-inside: avoid !important;}
- wkhtmltoxwkhtmltopdf linux 安裝
- php擴展php-wkhtmltox項目主頁: https://github.com/mreiferson/php-wkhtmltox
參考鏈接2
linux下查看yum/rpm/dpkg某軟件是否已安裝的方法
Error while loading shared libraries: libXrender.so.1 on Linux
靜態頁面
<html>
<head>
<meta http-equiv="Content_Type" content="text/html" charset="UTF-8">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="export echarts to pdf">
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script type="text/javascript" src="https://cdn.bootcss.com/echarts/3.7.2/echarts.simple.min.js"></script>
</head>
<style type="text/css">
@font-face{
font-family: Simsun;
src:url(“/usr/share/fonts/windows/tt.ttf”)
}
body{
font-family: tt ;
}
div{page-break-inside:avoid;}
table{
page-break-inside:avoid;
}
td{
border:1px solid #F00
}
</style>
<body>
<H1>First Title</H1>
<p>測試:test</p>
<p>by kang.cunhua;</p>
<H2>二級標題</H2>
<pre>
正文:
輕輕的我走了,
正如我輕輕的來;
我輕輕的招手,
作別西天的雲彩。
----
那河畔的金柳,
是夕陽中的新娘;
波光裏的豔影,
在我的心頭盪漾。
----
軟泥上的青荇⑴,
油油的在水底招搖⑵;
在康河的柔波里,
我甘心做一條水草!
----
那榆蔭下的一潭,
不是清泉,是天上虹;
揉碎在浮藻間,
沉澱着彩虹似的夢。
</pre>
<H3>三級標題</H3>
<table border="0" cellpadding="0" cellspacing="0">
<tr><td>第一行第一列</td><td colspan="2" align="center">第一行第一列</td><td>第一行第一列</td><td>第一行第一列</td></tr>
<tr><td>第一行第一列</td><td>第一行第一列</td><td>第一行第一列</td><td>第一行第一列</td><td>第一行第一列</td></tr>
<tr><td>第一行第一列</td><td>第一行第一列</td><td>第一行第一列</td><td>第一行第一列</td><td>第一行第一列</td></tr>
</table>
<!-- 爲ECharts準備一個具備大小(寬高)的Dom -->
<H4>四級標題</H4>
<div id="main" style="width: 600px;height:400px;"></div>
<script type="text/javascript">
// 基於準備好的dom,初始化echarts實例
var myChart = echarts.init(document.getElementById('main'));
// 指定圖表的配置項和數據
var option = {
title: {
text: 'ECharts 入門示例'
},
tooltip: {},
legend: {
data:['銷量']
},
xAxis: {
data: ["襯衫","羊毛衫","雪紡衫","褲子","高跟鞋","襪子"]
},
yAxis: {},
series: [{
name: '銷量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20]
}]
};
// 使用剛指定的配置項和數據顯示圖表。
myChart.setOption(option);
</script>
</body>
</html>
本文由作者:蠻大人 授權發佈
鏈接:https://opsdev.fun/2017/11/07/O1-8-20-Docker%E5%BF%AB%E9%80%9F%E9%AA%8C%E8%AF%81HTML%E5%AF%BC%E5%87%BAPDF%E9%AB%98%E6%95%88%E6%96%B9%E6%A1%88/
著作權歸作者所有。
轉載請聯繫作者獲得授權。
docker + k8s
此課程爲網絡直播課程,一共 10 個課時,每週上一個全天,歷時兩個多月。附加:錄播視頻+筆記+除課堂外的答疑時間(7次+)2019-1-13 開課,原價 5800 ,現在週年活動 100 定金抵 800
課程主講師:GY 老師
10 年一線軟件開發經驗,先後經歷了傳統安全公司,以及多家互聯網公司;在安全開發方面,曾開發過 Linux 防火牆、web 應用防火牆、Linux 安全內核加固,基於大流量的 Web 安全威脅分析等項目;在互聯網公司工作時,曾基於 DPDK 高性能網絡開發框架開發過基於全流量的網絡流量分析平臺和基於 Sflow 網絡流量分析平臺,基於Golang 開發SmartDNS 等;開發語言也是從C -> python -> golang 的轉變過程?現從事基於 K8S 和 Docker在私有云平臺建設方面的研發工作;具備豐富的Linux系統開發經驗、網絡開發經驗以及項目管理經驗;目前開發工作90+% 都在用 Golang,Golang 是一門簡潔、高效、強大且靈活的編程語言。
關於課程的具體內容想要了解的, 掃碼加小助手諮詢瞭解