一、簡介 之前也記錄過一篇關於把 HTML 文本或 HTML 文件轉換為 PDF 的博客,只是之前那種方法有些局限性。 後來又瞭解到 wkhtmltopdf.exe 這個工具,這個工具比起之前的那種方法簡直是太好用了。它是一個使用 Qt WebKit 引擎做渲染的,能夠把 HTML 文檔轉換成 PD ...
一、簡介
之前也記錄過一篇關於把 HTML 文本或 HTML 文件轉換為 PDF 的博客,只是之前那種方法有些局限性。
後來又瞭解到 wkhtmltopdf.exe 這個工具,這個工具比起之前的那種方法簡直是太好用了。
它是一個使用 Qt WebKit 引擎做渲染的,能夠把 HTML 文檔轉換成 PDF 文檔或圖片(image) 的命令行工具。
支持多個平臺,可在 windows、linux 等系統下運行。
你可以從這裡獲取到它:https://wkhtmltopdf.org/downloads.html
二、安裝
下載完成之後你需要先安裝它,然後你就能獲取到 wkhtmltopdf.exe 這個文件了,還包括有一個 wkhtmltoimage.exe 文件,
第一個文件是把 HTML 文檔轉換為 PDF 文檔的,後一個文件是把 HTML 文檔轉換為圖片的(Image),使用方法類似,只是調用的文件不一樣而已,這裡就不多做介紹。
我在安裝完成之後把 wkhtmltopdf.exe 這個文件放到了程式集所在的目錄,當然,你也可以不這麼做,但是就需要修改相應的路徑。
三、代碼
下麵不多說了,貼出我的代碼。
public partial class Form3 : Form { public Form3() { InitializeComponent(); string strHtml = "<p style='color:red;text-align:center;background-color:#000000;'>Hello World!<p><div style='width:150px;height:150px;background-color:blue;'></div>"; string htmlUrl = "https://wkhtmltopdf.org/downloads.html"; /// 把 HTML 文本內容轉換為 PDF HtmlTextConvertToPdf(strHtml, @"C:\Users\Administrator\Desktop\001.pdf"); /// 把 HTML 文件轉換為 PDF HtmlConvertToPdf(htmlUrl, @"C:\Users\Administrator\Desktop\002.pdf"); } /// <summary> /// HTML文本內容轉換為PDF /// </summary> /// <param name="strHtml">HTML文本內容</param> /// <param name="savePath">PDF文件保存的路徑</param> /// <returns></returns> public bool HtmlTextConvertToPdf(string strHtml, string savePath) { bool flag = false; try { string htmlPath = HtmlTextConvertFile(strHtml); flag = HtmlConvertToPdf(htmlPath, savePath); File.Delete(htmlPath); } catch { flag = false; } return flag; } /// <summary> /// HTML轉換為PDF /// </summary> /// <param name="htmlPath">可以是本地路徑,也可以是網路地址</param> /// <param name="savePath">PDF文件保存的路徑</param> /// <returns></returns> public bool HtmlConvertToPdf(string htmlPath, string savePath) { bool flag = false; CheckFilePath(savePath); ///這個路徑為程式集的目錄,因為我把應用程式 wkhtmltopdf.exe 放在了程式集同一個目錄下 string exePath = AppDomain.CurrentDomain.BaseDirectory.ToString() + "wkhtmltopdf.exe"; if (!File.Exists(exePath)) { throw new Exception("No application wkhtmltopdf.exe was found."); } try { ProcessStartInfo processStartInfo = new ProcessStartInfo(); processStartInfo.FileName = exePath; processStartInfo.WorkingDirectory = Path.GetDirectoryName(exePath); processStartInfo.UseShellExecute = false; processStartInfo.CreateNoWindow = true; processStartInfo.RedirectStandardInput = true; processStartInfo.RedirectStandardOutput = true; processStartInfo.RedirectStandardError = true; processStartInfo.Arguments = GetArguments(htmlPath, savePath); Process process = new Process(); process.StartInfo = processStartInfo; process.Start(); process.WaitForExit(); ///用於查看是否返回錯誤信息 //StreamReader srone = process.StandardError; //StreamReader srtwo = process.StandardOutput; //string ss1 = srone.ReadToEnd(); //string ss2 = srtwo.ReadToEnd(); //srone.Close(); //srone.Dispose(); //srtwo.Close(); //srtwo.Dispose(); process.Close(); process.Dispose(); flag = true; } catch { flag = false; } return flag; } /// <summary> /// 獲取命令行參數 /// </summary> /// <param name="htmlPath"></param> /// <param name="savePath"></param> /// <returns></returns> private string GetArguments(string htmlPath,string savePath) { if (string.IsNullOrEmpty(htmlPath)) { throw new Exception("HTML local path or network address can not be empty."); } if(string.IsNullOrEmpty(savePath)) { throw new Exception("The path saved by the PDF document can not be empty."); } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(" --page-height 100 "); //頁面高度100mm stringBuilder.Append(" --page-width 100 "); //頁面寬度100mm stringBuilder.Append(" --header-center 我是頁眉 "); //設置居中顯示頁眉 stringBuilder.Append(" --header-line "); //頁眉和內容之間顯示一條直線 stringBuilder.Append(" --footer-center \"Page [page] of [topage]\" "); //設置居中顯示頁腳 stringBuilder.Append(" --footer-line "); //頁腳和內容之間顯示一條直線 stringBuilder.Append(" " + htmlPath + " "); //本地 HTML 的文件路徑或網頁 HTML 的URL地址 stringBuilder.Append(" " + savePath + " "); //生成的 PDF 文檔的保存路徑 return stringBuilder.ToString(); } /// <summary> /// 驗證保存路徑 /// </summary> /// <param name="savePath"></param> private void CheckFilePath(string savePath) { string ext = string.Empty; string path = string.Empty; string fileName = string.Empty; ext = Path.GetExtension(savePath); if (string.IsNullOrEmpty(ext) || ext.ToLower() != ".pdf") { throw new Exception("Extension error:This method is used to generate PDF files."); } fileName = Path.GetFileName(savePath); if (string.IsNullOrEmpty(fileName)) { throw new Exception("File name is empty."); } try { path = savePath.Substring(0, savePath.IndexOf(fileName)); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } } catch { throw new Exception("The file path does not exist."); } } /// <summary> /// HTML文本內容轉HTML文件 /// </summary> /// <param name="strHtml">HTML文本內容</param> /// <returns>HTML文件的路徑</returns> public string HtmlTextConvertFile(string strHtml) { if (string.IsNullOrEmpty(strHtml)) { throw new Exception("HTML text content cannot be empty."); } try { string path = AppDomain.CurrentDomain.BaseDirectory.ToString() + @"html\"; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } string fileName = path + DateTime.Now.ToString("yyyyMMddHHmmssfff") + new Random().Next(1000, 10000) + ".html"; FileStream fileStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite); StreamWriter streamWriter = new StreamWriter(fileStream, Encoding.Default); streamWriter.Write(strHtml); streamWriter.Flush(); streamWriter.Close(); streamWriter.Dispose(); fileStream.Close(); fileStream.Dispose(); return fileName; } catch { throw new Exception("HTML text content error."); } } }
PS:在這裡我遇到了一個問題,剛開始設置的命令行參數不起作用,比如:--page-height 100 等。
我也查看了輸出的錯誤信息,後來發現是因為 wkhtmltopdf.exe 這個文件的路徑存在中文的目錄。
然後我就把 wkhtmltopdf.exe 這個文件所在路徑的所有目錄都改為了英文,就這樣就可以了。
四、命令行參數
下麵是一些命令行參數的介紹:
全局選項: --collate 列印多個副本時進行檢查(預設設置) --no-collate 列印多個副本時不進行檢查 --cookie-jar <path> 從指定的cookie JAR文件中讀寫 cookie 數據 --copies <number> 列印 PDF 文件的份數(預設值為:1) --dpi <dpi> 設置一個解析度,對於 X11 系統沒有作用(預設值為:96) --extended-help 相對 -H 參數的設置,顯示更詳細的說明文檔 --grayscale 將生成灰度的 PDF 文檔,占用空間小,但是不會有彩色 --help 顯示幫助信息 --htmldoc 輸出程式的 HTML 幫助文檔 --image-dpi <integer> 當頁面存在內嵌圖片時,指定圖像的解析度(預設值為:600) --image-quality <interger> 當使用 JPEG 演算法壓縮圖片時,指定圖像的質量(預設值為:94) --license 輸出授權許可信息並退出 --lowquality 生成低質量的 PDF/PS,能夠減少最終生成文檔所占用的存儲空間 --manpage 輸出程式的手冊頁 --quiet 靜默模式,不輸出任何信息 --read-args-from-stdin 從標準輸入讀取命令行參數 --readme 輸出程式的 Readme 文檔 --version 輸出版本信息並退出 --no-pdf-compression 設置為不要對 PDF 對象使用無損壓縮 --margin-bottom <unitreal> 設置頁面的底邊距,單位毫米(mm) --margin-left <unitreal> 設置頁面的左邊距 (預設值為:10mm) --margin-right <unitreal> 設置頁面的右邊距 (預設值為:10mm) --margin-top <unitreal> 設置頁面的上邊距,單位毫米(mm) --page-size <Size> 設置頁面的大小,如:A4、Letter等(預設值為:A4) --page-height <unitreal> 設置頁面高度,單位毫米(mm) --page-width <unitreal> 設置頁面寬度,單位毫米(mm) --orientation <orientation> 設置文檔模式為風景或肖像(預設值為:肖像) --title <text> 生成的 PDF 文檔的標題(如果沒有指定,則使用第一個文檔的標題) 大綱選項: --dump-default-toc-xsl 轉儲到預設的 TOC xsl 樣式表到標準輸出文件 --dump-outline <file> 將大綱轉儲到指定的文件(XML 文件) --outline 在生成的 PDF 文檔中添加大綱(預設設置) --no-outline 不要在生成的 PDF 文檔中添加大綱 --outline-depth <level> 設置大綱的深度(預設值為:4) 頁面選項: --allow <path> 允許載入指定文件夾中的文件(可重覆使用此參數指定多個文件) --background 輸出頁面背景到 PDF 文檔(預設設置) --no-background 不輸出頁面背景到 PDF 文檔 --bypass-proxy-for <value> 設置主機的代理(可重覆指定多個代理) --cache-dir <path> Web緩存目錄 --checkbox-checked-svg <path> 使用指定的SVG文件渲染選中的覆選框 --checkbox-svg <path> 使用指定的SVG文件渲染未選中的覆選框 --cookie <name> <value> 設置訪問網頁時額外的 cookie,value 應該是 url 編碼的(可重覆使用此參數指定多個 cookie) --custom-header <name> <value> 設置訪問網頁時額外的 HTTP 頭(可重覆使用此參數指定多個 HTTP 頭) --custom-header-propagation 為每個資源請求添加自定義的 HTTP 頭 --no-custom-header-propagation 不要為每個資源請求添加自定義的 HTTP 頭 --debug-javascript 顯示 JavaScript 調試輸出的內容 --no-debug-javascript 不顯示 JavaScript 調試輸出的內容(預設設置) --encoding <encoding> 設置輸入文本的預設編碼 --disable-external-links 禁止頁面中的外鏈生成超鏈接 --enable-external-links 允許頁面中的外鏈生成超鏈接(預設設置) --disable-forms 不要將 HTML 表單轉換為 PDF 表單(預設設置) --enable-forms 將 HTML 表單轉換為 PDF 表單 --images 載入圖片並輸出到 PDF 文檔(預設設置) --no-images 在生成的 PDF 文檔中過濾掉圖片 --disable-internal-links 禁止頁面中的內鏈生成超鏈接 --enable-internal-links 允許頁面中的內鏈生成超連接(預設設置) --disable-javascript 禁止 Web 頁面運行 JavaScript --enable-javascript 允許 Web 頁面運行 JavaScript(預設設置) --javascript-delay <msec> 延遲指定的時間,等待 JavaScript 執行完成,單位毫秒(ms)(預設值為:200) --load-error-handling <handler> 指定如何處理無法載入的頁面:abort、ignore、skip(預設值為:abort) --load-media-error-handling <handler> 指定如何處理無法載入的媒體文件:abort、ignore、skip(預設值為:ignore) --disable-local-file-access 不允許一個本地文件載入其他的本地文件,使用命令行參數 --allow 指定的目錄除外。 --enable-local-file-access 允許將本地文件轉換到其他本地文件中讀取(預設設置) --exclude-from-outline 不要將頁麵包含在內容表和大綱中 --include-in-outline 將頁麵包含在內容表和大綱中(預設設置) --page-offset <offset> 設置頁碼的起始值(預設值為:0) --minimum-font-size <int> 設置最小的字體大小 --disable-plugins 禁用已安裝的插件(預設設置) --enable-plugins 啟用已安裝的插件(但插件可能不起作用) --post <name> <value> 添加一個附加欄位(可以重覆使用該參數添加多個附加欄位) --post-file <name> <value> 添加一個附加文件(可以重覆使用該參數添加多個附加文件) --print-media-type 使用列印媒體類型代替屏幕 --no-print-media-type 不使用列印媒體類型代替屏幕(預設設置) --proxy <proxy> 使用代理 --radiobutton-checked-svg <path> 使用指定的SVG文件渲染選中的單選按鈕 --radiobutton-svg <path> 使用指定的SVG文件渲染未選中的單選按鈕 --run-sript <js> 在頁面載入完成後運行這個額外的 JavaScript(可以重覆使用該參數添加多個額外的 JavaScript) --disable-smart-shrinking 禁用智能收縮策略 --enable-smart-shrinking 啟用智能收縮策略(預設設置) --stop-slow-scripts 停止運行緩慢的 JavaScript 代碼(預設設置) --no-stop-slow-scripts 不停止運行緩慢的 JavaScript 代碼 --disable-toc-back-links 禁止從標頭鏈接到內容表(預設設置) --enable-toc-back-links 允許從標頭鏈接到內容表 --user-style-sheet <url> 指定一個用戶樣式表,以便載入每個頁面 --username <username> HTTP 身份認證的用戶名 --password <password> HTTP 身份認證的密碼 --viewport-size <> 設置視窗大小,需要自定義滾動條或 CSS 屬性來自適應視窗大小 --window-status <windowStatus> 等到window.status等於這個字元串前渲染頁面 --zoom <float> 設置轉換成 PDF 時頁面的縮放比例(預設值為:1) --default-header 添加一個預設的頁眉,左邊是頁面的名稱,右邊是頁碼,是下麵的縮寫: --header-left='[webpage]' --header-right='[page]/[toPage]' --top 2cm --header-line 頁眉和頁腳選項: --footer-left <text> 居左顯示頁腳文本 --footer-center <text> 居中顯示頁腳文本 --footer-right <text> 居右顯示頁腳文本 --footer-font-name <name> 設置頁腳的字體名稱(預設值為:Arial) --footer-font-size <size> 設置頁腳的字體大小(預設值為:12) --footer-html <url> 添加一個 HTML 作為頁腳 --footer-line 在頁腳上方顯示一條直線 --no-footer-line 不在頁腳上方顯示一條直線(預設設置) --footer-spacing <real> 設置頁腳與內容之間的間距,單位毫米(mm)(預設值為:0) --header-left <text> 居左顯示頁眉文本 --header-center <text> 居中顯示頁眉文本 --header-right <text> 居右顯示頁眉文本 --header-font-name <name> 設置頁眉的字體名稱(預設值為:Arial) --header-font-size <size> 設置頁眉的字體大小(預設值為:12) --header-html <url> 添加一個 HTML 作為頁眉 --header-line 在頁眉下方顯示一條直線 --no-header-line 不在頁眉下方顯示一條直線(預設設置) --header-spacing <real> 設置頁眉與內容之間的間距,單位毫米(mm)(預設值為:0) --replace <name> <value> 在頁眉和頁腳中替換指定名稱的值(可以重覆使用該參數指定多個需要替換的名稱和值) 內容表選項: --disable-dotted-lines 不要在 TOC 中使用虛線 --toc-header-text <text> 設置 TOC 的標題文本(預設值為:內容表) --toc-level-indentation <width> 在 TOC 縮進每一級的標題長度(預設值為:1em) --disable-toc-links 在 TOC 中不生成指向內容錨點的超鏈接 --toc-text-size-shrink <real> 在 TOC 中的每一級標題,字體按這個比例縮放(預設值為:0.8) --xsl-style-sheet <file> 使用指定的 XSL 樣式表列印內容表 頁眉和頁腳: 頁眉和頁腳可以使用參數 --header-* 和 --footer-* 添加到文檔中。 有些參數也需要提供一個字元串 text 作為參數值。例如:--header-left 可以在 text 中使用以下變數,將會把以下變數替換為對應的值。 * [page] 當前正在列印的頁面的頁碼 * [frompage] 列印的第一頁的頁碼 * [topage] 列印的最後一頁的頁碼 * [webpage] 當前正在列印的頁面的 URL * [section] 當前正在列印的章節的名稱 * [subsection] 當前正在列印的分段的名稱 * [date] 本地系統格式的當前日期 * [isodate] ISO 8601 擴展格式的當前日期 * [time] 本地系統格式的當前時間 * [title] 當前頁對象的標題 * [doctitle] 輸出文檔的標題 * [sitepage] 當前正在處理的對象中當前頁面的頁碼 * [sitepages] 當前正在處理的對象中的總頁數 舉個例子: --header-right "Page [page] of [toPage]", 會在頁面的右上角生成一個類似 Page x of y 的字元串, 其中 x 是當前頁面的頁碼, y 是當前文檔最後一頁的頁碼。
五、推薦
下麵推薦兩篇比較好的文章,一篇是官網的英文版的介紹,另一篇是中文版的介紹。
具體的大家自己去看吧。
英文版推薦:https://wkhtmltopdf.org/usage/wkhtmltopdf.txt
中文版推薦:http://www.jianshu.com/p/4d65857ffe5e