在工作中,有很多數據需要導出成PDF,比如賬單、數據報表、簡歷等等。有很多方法可以做PDF的導出,JAVA就有很好的組件可以做這個事情。可以根據項目做不同的選擇,下面我們簡單探討一下。
常用的導出方法對比調研對
調研對象 | 優點 | 缺點 | 分頁 | 圖片 |
---|---|---|---|---|
jsPDF |
1、整個過程在客戶端執行(不需要服務器參與),調用簡單 |
1、生成的pdf爲圖片形式,且內容失真 |
支持 |
支持 |
iText |
1、功能基本可以實現,比較靈活2、生成pdf質量較高 |
1、對html標籤嚴;格,少一個結束標籤就會報錯;2、後端實現複雜,服務器需要安裝字體;3、圖片渲染比較複雜(暫時還沒解決) |
支持 |
支持 |
wkhtmltopdf |
1、調用方式簡單(只需執行一行腳本);2、生成pdf質量較高 |
1、服務器需要安裝wkhtmltopdf環境;2、根據網址生成pdf,對於有權限控制的頁面需要在攔截器進行處理 |
支持 |
支持 |
goPdf |
1.可以用Golang實現pdf的生成 |
1. 後端爲golang寫的服務;2. 需要開發者實現所有元素的繪製,代碼量大、容易出錯、不夠靈活 |
支持 |
支持 |
html2canvas+jsPDF
原理是利用html2canvas遍歷頁面中的dom節點,渲染成canvas image,再用jsPDF把canvas image轉化爲pdf,最後轉化的pdf的內容都是圖片形式,類似於把整個網頁截圖、切割,再一頁一頁拼接成一個完整的pdf。
這種方法的優點是所有的過程都由js在客戶端完成,不需要依賴服務器。
目前發現的兩個比較明顯的缺點:
1、生成的pdf質量不高,失真比較嚴重;
2、在分頁處如果有圖片的話,不會自動識別隔頁處理(甚至一行文字也能給你上下一分爲二),圖片也會很容易被一分爲二
iText
iText是一個第三方報表java插件,可以在後端利用java隨意生成、轉化pdf文件,提供了很多api,比較靈活。
需要注意的是:
1、如果頁面中有中文,服務器端需要下載字體庫simsun.ttc,在後臺進行引用,同時在頁面的樣式中加入對應字體的定義
2、頁面中如果有圖片,如果圖片引用是絕對路徑或者base64則不用考慮,如果是相對路徑,需要在後臺用renderer.getSharedContext().setBaseURL("圖片絕對路徑目錄");來指定圖片路徑,否則圖片無法渲染。
3、要轉化的頁面必須是標準的XHTML頁面,有一處不符合規範就會報錯
wkhtmltopdf
wkhtmltopdf是一個可以把html轉爲pdf的插件,有windows、linux等平臺的版本,最大的特點就是使用簡單,語言無關性
使用方法:
wkhtmltopdf https://www.baidu.com/ feishu.pdf
注意:需要按照插件
爲什麼要選擇wkhtmltopdf
1. 可以使用html模版作爲頁面的基礎框架
2. 可以比較容易的把數據灌入html模版
3. 對於html修改比較靈活,顏色及樣式比較容易修改與構建
比如Golang對於HTML模版支持的還是比較好的,可以把HTML模版定義成類似下面的格式:
<div class="item inline-block">
<h4>用戶名:</h4>
<p>{{.UserName}}</p>
</div>
<div class="item inline-block">
<h4>密碼:</h4>
<p>{{.Password}}</p>
</div>
下面的函數可以方便的讀取Globalization的HTML模版,然後就可以調用wkhtmltopdf進行轉換。
func GeneratePdf(locale string, data ExportData) ([]byte, error) {
ext := "html"
htmlTplName := utils.GetHtmlTemplatePath("use_info", ext, locale)
tmpl, err := template.ParseFiles(htmlTplName)
if err != nil {
return nil, err
}
buf := &bytes.Buffer{}
tmpl.Execute(buf, data)
return buf.Bytes(), nil
}
對於golang調用wkhtmltopdf,這裏就不再闡述了,可以在github上搜一個庫進行調用。(https://github.com/lawenliu/wkhtmltopdf-go)