最近項目上需要做一個線上合約的功能,合約有電子版,需要把網頁版的合約直接生產pdf,要求樣式不能亂,有頁碼有頁首頁尾等等,在網上搜尋一段時間後,找到了一個工具叫: wkhtmltopdf ,這應該是國外的一款免費軟體,有Windows,mac,linux版,直接在命令列調用,這幾天完成了一個demo,順便總結一下。
這是此工具的官網: http://wkhtmltopdf.org/downloads.html 所需要的工具可以在這裡下載,免費。
// 2017年3月7日15:49:58 好像這個工具無法解析angularjs……
先貼上demo代碼:
調用類:
package WkHtmlToPDF;import java.io.File;import java.util.Date;/** * Created by Jerry on 2017/2/13. * God Bless Me */public class wkhtmltopdf { //wkhtmltopdf 在系統中的路徑 private static final String toPdfTool = "C:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltopdf.exe"; public static void main(String[] args) { Date date = new Date(); String fileName = String.valueOf(date.getTime()) + ".pdf"; convert("http://www.jianshu.com/p/74e3a6ee4ae8", "D:\\PDF\\" + fileName); } /** * html轉pdf * * @param srcPath html路徑,可以是硬碟上的路徑,也可以是網路路徑 * @param destPath pdf儲存路徑 * @return 轉換成功返回true */ public static boolean convert(String srcPath, String destPath) { File file = new File(destPath); File parent = file.getParentFile(); //如果pdf儲存路徑不存在,則建立路徑 if (!parent.exists()) { parent.mkdirs(); } StringBuilder cmd = getFormal();// StringBuilder cmd = test1(); //html路徑 即目標網頁路徑 cmd.append(" "); cmd.append(srcPath); cmd.append(" "); //pdf儲存路徑 cmd.append(destPath); boolean result = true; try { Process proc = Runtime.getRuntime().exec(cmd.toString()); HtmlToPdfInterceptor error = new HtmlToPdfInterceptor(proc.getErrorStream()); HtmlToPdfInterceptor output = new HtmlToPdfInterceptor(proc.getInputStream()); error.start(); output.start(); proc.waitFor(); } catch (Exception e) { result = false; e.printStackTrace(); } return result; } /** * 標準格式 * * @return */ public static StringBuilder getFormal() { StringBuilder cmd = new StringBuilder(); //wkhtmltopdf 在系統中的路徑 cmd.append(toPdfTool); cmd.append(" "); cmd.append(" --header-line");//頁首下面的線// cmd.append(" --footer-line");//頁尾上面的線 cmd.append(" --footer-center [page]/[topage]"); //在頁尾中心放置頁碼// cmd.append(" --header-right 這裡是我們系統的頁首"); //頁首中間放置文字 cmd.append(" --header-html http://localhost:8090/myheader.html"); //頁首中間放置圖片 cmd.append(" --header-spacing 5 ");// (設定頁首和內容的距離,預設0 ) cmd.append(" --margin-top 20mm "); //設定頁面上邊距 (default 10mm) cmd.append(" cover http://localhost:8090/firstPage.html "); return cmd; } public static StringBuilder test1() { StringBuilder cmd = new StringBuilder(); //wkhtmltopdf 在系統中的路徑 cmd.append(toPdfTool);// cmd.append(" --cover http://localhost:8090/firstPage.html"); cmd.append(" -T 15mm"); cmd.append(" --header-spacing 5"); cmd.append(" --outline"); cmd.append(" cover http://image.baidu.com"); cmd.append(" "); return cmd; }}
工具類:
package WkHtmlToPDF;/** * Created by Jerry on 2017/2/13. * God Bless Me */import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;/** * 當java調用wkhtmltopdf時,用於擷取wkhtmltopdf返回的內容 */public class HtmlToPdfInterceptor extends Thread { private InputStream is; public HtmlToPdfInterceptor(InputStream is){ this.is = is; } public void run(){ try{ InputStreamReader isr = new InputStreamReader(is, "utf-8"); BufferedReader br = new BufferedReader(isr); String line = null; while ((line = br.readLine()) != null) { System.out.print(line.toString()); //輸出內容 } }catch (IOException e){ e.printStackTrace(); } }}
基本上你複製這兩個類,安裝完這個工具,就可以直接跑起來了。
這裡有幾點我自己探索的經驗:
雖然我看的幾篇資料裡面都沒有說命令執行有先後的區別,但很明顯,在產生首頁的時候,必須把
cmd.append(" cover http://localhost:8090/firstPage.html ");
寫在最後,不然就會報錯,如果哪位知道原因,可以聯絡我一下 QQ:527397749
還有一點容易忽略的,是每個命令的最後一定要加空格,不然會出現命令粘連的問題,很基礎,很難發現。
附上常用命令表;
Linux:wkhtmltopdf [OPTIONS]… [More input files] windows:wkhtmltopdf.exe [OPTIONS]… [More input files] 常規選項 –allow 允許載入從指定的檔案夾中的檔案或檔案(可重複) –book* 設定一會列印一本書的時候,通常設定的選項 –collate 列印多份副本時整理 –cookie 設定一個額外的cookie(可重複) –cookie-jar 讀取和寫入的Cookie,並在提供的cookie jar檔案 –copies 複印列印成pdf檔案數(預設為1) –cover* 使用HTML檔案作為封面。它會帶頁首和頁尾的TOC之前插入 –custom-header 設定一個附加的HTTP頭(可重複) –debug-JavaScript 顯示的javascript調試輸出 –default-header* 添加一個預設的頭部,與頁面的左邊的名稱,頁面數到右邊,例如: –header-left ‘[webpage]’ –header-right ‘[page]/[toPage]’ –header-line –disable-external-links* 禁止產生連結到遠程網頁 –disable-internal-links* 禁止使用本地連結 –disable-javascript 禁止讓網頁執行JavaScript –disable-pdf-compression* 禁止在PDF對象使用無損壓縮 –disable-smart-shrinking* 禁止使用WebKit的智能戰略收縮,使像素/ DPI比沒有不變 –disallow-local-file-access 禁止允許轉換的本地檔案讀取其他本地檔案,除非explecitily允許用 –allow –dpi 顯式更改DPI(這對基於X11的系統沒有任何影響) –enable-plugins 啟用已安裝的外掛程式(如Flash –encoding 設定預設的文字編碼 –extended-help 顯示更廣泛的協助,詳細介紹了不常見的命令開關 –forms* 開啟HTML表單欄位轉換為PDF表單域 –grayscale PDF格式將在灰階產生 –help Display help –htmldoc 輸出程式HTML協助 –ignore-load-errors 忽略claimes載入過程中已經遇到了一個錯誤頁面 –lowquality 產生低品質的PDF/ PS。有用縮小結果文檔的空間 –manpage 輸出程式手冊頁 –margin-bottom 設定頁面下邊距 (default 10mm) –margin-left 將左邊頁面邊界 (default 10mm) –margin-right 設定頁面右邊距 (default 10mm) –margin-top 設定頁面上邊距 (default 10mm) –minimum-font-size 最小字型大小 (default 5) –no-background 不列印背景 –orientation 設定方向為橫向或縱向 –page-height 頁面高度 (default unit millimeter) –page-offset* 設定起始頁碼 (default 1) –page-size 設定紙張大小: A4, Letter, etc. –page-width 頁面寬度 (default unit millimeter) –password HTTP驗證密碼 –post Add an additional post field (repeatable) –post-file Post an aditional file (repeatable) –print-media-type* 使用的列印介質類型,而不是螢幕 –proxy 使用代理 –quiet Be less verbose –read-args-from-stdin 讀取標準輸入的命令列參數 –readme 輸出程式自述 –redirect-delay 等待幾毫秒為JS-重新導向(default 200) –replace* 替換名稱,值的頁首和頁尾(可重複) –stop-slow-scripts 停止運行緩慢的JavaScripts –title 產生的PDF檔案的標題(第一個文檔的標題使用,如果沒有指定) –toc* 插入的內容的表中的檔案的開頭 –use-xserver* 使用X伺服器(一些外掛程式和其他的東西沒有X11可能無法正常工作) –user-style-sheet 指定使用者的樣式表,載入在每一頁中 –username HTTP認證的使用者名稱 –version 輸出版本資訊退出 –zoom 使用這個縮放因子 (default 1)頁首和頁尾選項 –header-center* (設定在中心位置的頁首內容) –header-font-name* (default Arial) (設定頁首的字型名稱) –header-font-size* (設定頁首的字型大小) –header-html* (添加一個HTML頁首,後面是網址) –header-left* (靠左對齊的頁首文本) –header-line* (顯示一條線在頁首下) –header-right* (靠右對齊頁首文本) –header-spacing* (設定頁首和內容的距離,預設0) –footer-center* (設定在中心位置的頁尾內容) –footer-font-name* (設定頁尾的字型名稱) –footer-font-size* (設定頁尾的字型大小default 11) –footer-html* (添加一個HTML頁尾,後面是網址) –footer-left* (靠左對齊的頁尾文本) –footer-line* 顯示一條線在頁尾內容上) –footer-right* (靠右對齊頁尾文本) –footer-spacing* (設定頁尾和內容的距離) ./wkhtmltopdf –footer-right ‘[page]/[topage]’ http://www.baidu.com baidu.pdf ./wkhtmltopdf –header-center ‘報表’ –header-line –margin-top 2cm –header-line http://192.168.212.139/oma/ oma.pdf 表內容選項中 –toc-depth* Set the depth of the toc (default 3) –toc-disable-back-links* Do not link from section header to toc –toc-disable-links* Do not link from toc to sections –toc-font-name* Set the font used for the toc (default Arial) –toc-header-font-name* The font of the toc header (if unset use –toc-font-name) –toc-header-font-size* The font size of the toc header (default 15) –toc-header-text* The header text of the toc (default Table Of Contents) –toc-l1-font-size* Set the font size on level 1 of the toc (default 12) –toc-l1-indentation* Set indentation on level 1 of the toc (default 0) –toc-l2-font-size* Set the font size on level 2 of the toc (default 10) –toc-l2-indentation* Set indentation on level 2 of the toc (default 20) –toc-l3-font-size* Set the font size on level 3 of the toc (default 8) –toc-l3-indentation* Set indentation on level 3 of the toc (default 40) –toc-l4-font-size* Set the font size on level 4 of the toc (default 6) –toc-l4-indentation* Set indentation on level 4 of the toc (default 60) –toc-l5-font-size* Set the font size on level 5 of the toc (default 4) –toc-l5-indentation* Set indentation on level 5 of the toc (default 80) –toc-l6-font-size* Set the font size on level 6 of the toc (default 2) –toc-l6-indentation* Set indentation on level 6 of the toc (default 100) –toc-l7-font-size* Set the font size on level 7 of the toc (default 0) –toc-l7-indentation* Set indentation on level 7 of the toc (default 120) –toc-no-dots* Do not use dots, in the toc 輪廓選項 –dump-outline 轉儲目錄到一個檔案 –outline 顯示目錄(文章中h1,h2來定) –outline-depth 設定目錄的深度(預設為4) 頁尾和頁首 * [page] 由當前正在列印的頁的數目代替 * [frompage] 由要列印的第一頁的數量取代 * [topage] 由最後一頁要列印的數量取代 * [webpage] 通過正在列印的頁面的URL替換 * [section] 由當前節的名稱替換 * [subsection] 由當前小節的名稱替換 * [date] 由當前日期系統的本地格式取代 * [time] 由目前時間,系統的本地格式取代
有一篇不錯的文章: http://www.jianshu.com/p/4d65857ffe5e 大家可以一併閱讀,其他資料我覺得沒什麼可看的了,因為我都看了一遍。
歡迎留言探討。