html頁面導出pdf,本來是一件很簡單的事情,在瀏覽器直接打印(Mac快捷鍵為⌘+p;Windows快捷鍵為ctrl+p),就可以把頁面另存為pdf文件,但對於要經常把頁面導出為pdf的用戶來說並不友好,一個合格程序員的標准就是:做出來的軟件豬都要會用,否則你就是豬。
調研了幾種html導出pdf的實現方式,這里把要點記錄下來分享下。
調研對象 優點 缺點 分頁 圖片 表格 鏈接 中文 特殊字符、樣式 導出樣例 備注
上面三種是着重調研的三種方式,下面進行簡單介紹。
一、html2canvas+jsPDF
這種方式的原理是利用html2canvas遍歷頁面中的dom節點,渲染成canvas image,再用jsPDF把canvas image轉化為pdf,最后轉化的pdf的內容都是圖片形式,類似於把整個網頁截圖、切割,再一頁一頁拼接成一個完整的pdf。
代碼樣例
html:
<button id="exportToPdf">導出為PDF</button>
<div id="export_content">
這里是要導出為pdf中的內容
</div>
1
2
3
4
javascript(需要依賴jspdf和html2canvas相關js):
<script src="js/jspdf.debug.js"></script>
<script src="js/html2canvas.js"></script>
<script type="text/javascript">
var downPdf = document.getElementById("exportToPdf");
downPdf.onclick = function () {
html2canvas(
document.getElementById("export_content"),
{
dpi: 172,//導出pdf清晰度
onrendered: function (canvas) {
var contentWidth = canvas.width;
var contentHeight = canvas.height;
//一頁pdf顯示html頁面生成的canvas高度;
var pageHeight = contentWidth / 592.28 * 841.89;
//未生成pdf的html頁面高度
var leftHeight = contentHeight;
//pdf頁面偏移
var position = 0;
//html頁面生成的canvas在pdf中圖片的寬高(a4紙的尺寸[595.28,841.89])
var imgWidth = 595.28;
var imgHeight = 592.28 / contentWidth * contentHeight;
var pageData = canvas.toDataURL('image/jpeg', 1.0);
var pdf = new jsPDF('', 'pt', 'a4');
//有兩個高度需要區分,一個是html頁面的實際高度,和生成pdf的頁面高度(841.89)
//當內容未超過pdf一頁顯示的范圍,無需分頁
if (leftHeight < pageHeight) {
pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);
} else {
while (leftHeight > 0) {
pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
leftHeight -= pageHeight;
position -= 841.89;
//避免添加空白頁
if (leftHeight > 0) {
pdf.addPage();
}
}
}
pdf.save('content.pdf');
},
//背景設為白色(默認為黑色)
background: "#fff"
})
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
這種方法的優點是所有的過程都由js在客戶端完成,不需要依賴服務器。
目前發現的兩個比較明顯的缺點:
1、生成的pdf質量不高,失真比較嚴重(不過在github上這個方法可以適當提高下生成pdf的清晰度https://github.com/niklasvh/html2canvas/pull/1087);
2、在分頁處如果有圖片的話,不會自動識別隔頁處理(甚至一行文字也能給你上下一分為二),而是無情地把圖片一分為二,滿滿的違和感~如下圖:
github上有一篇文章說明比較詳細,還有具體的demo:https://github.com/linwalker/render-html-to-pdf
二、iText
iText是一個第三方報表java插件,可以在后端利用java隨意生成、轉化pdf文件,提供了很多api,比較靈活。
代碼樣例
pom依賴:
<dependency>
<groupId>org.eclipse.birt.runtime.3_7_1</groupId>
<artifactId>com.lowagie.text</artifactId>
<version>2.1.7</version>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf</artifactId>
<version>9.0.8</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.4.2</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
java實現:
ITextRenderer renderer = new ITextRenderer();
ITextFontResolver fontResolver = renderer.getFontResolver();
fontResolver.addFont("/Users/hehe/share/Fonts/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
OutputStream os = new FileOutputStream("/Users/hehe/Desktop/iTextPDF.pdf");
String htmlstr = HttpHandler.sendGet("http://localhost:10086/test/iTextPDF.html");//HttpHandler.sendGet只是單純獲得指定網頁的html字符串內容
renderer.setDocumentFromString(htmlstr);
renderer.layout();
renderer.createPDF(os);
1
2
3
4
5
6
7
8
以上只是簡單利用html字符串來生成pdf,需要注意的是:
1、如果頁面中有中文,服務器端需要下載字體庫simsun.ttc,在后台進行引用,同時在頁面的樣式中加入對應字體的定義,如:body{font-family: SimSun;},否則中文無法渲染(中文處渲染出來的效果是空白);
2、頁面中如果有圖片,如果圖片引用是絕對路徑或者base64則不用考慮,如果是相對路徑,需要在后台用renderer.getSharedContext().setBaseURL("圖片絕對路徑目錄");來指定圖片路徑,否則圖片無法渲染。
3、要轉化的頁面必須是標准的XHTML頁面,有一處不符合規范就會報錯,小編再試的時候就經常報諸如org.xml.sax.SAXParseException;lineNumber: 24; columnNumber: 6;元素類型 "span" 必須由匹配的結束標記 "</span> 終止"之類的錯誤,所以如果要用iText來大量爬取網絡中的頁面的話,還是放棄吧,畢竟網上很多頁面都是不標准的~
三、wkhtmltopdf
wkhtmltopdf是一個可以把html轉為pdf的插件,有windows、linux等平台的版本,最大的特點就是使用簡單,語言無關性。
1、下載:官網下載 https://wkhtmltopdf.org/downloads.html
2、執行:該插件是“綠色版”,無需編譯安裝,下載解壓后,在bin目錄下有wkhtmltoimage和wkhtmltopdf兩個文件,生成pdf可以直接運行wkhtmltopdf(也可以把bin目錄配置到環境變量),執行wkhtmltopdf -V查看是否可以執行。
執行的時候可能會報錯wkhtmltopdf: error while loading shared libraries: libXrender.so.1 或者 ./wkhtmltopdf: error while loading shared libraries: libfontconfig.so.1: cannot open shared object file: No such file or directory 具體解決方法可參考https://www.svennd.be/wkhtmltopdf-error-while-loading-shared-libraries-libxrender-so-1/
如果執行完打印出wkhtmltopdf的版本號,則說明OK了,下面來一個打印html頁面的例子試試看,就把本頁面轉化成pdf吧:
wkhtmltopdf --disable-smart-shrinking https://blog.csdn.net/huyuyang6688/article/details/79710704 myBlog.pdf
1
執行完之后,就會在當前目錄生成一個pdf(當然生成pdf的目錄可以指定),--disable-smart-shrinking 這個參數是關閉縮放,如果不加的話,生成的pdf內容會特別“瘦”,不造為啥這個命令在mac環境下不是很有效,不敢在linux環境生成的PDF是正常的。具體更詳細的用法可以參考如下文章:
1、HTML 轉 PDF 之 wkhtmltopdf 工具簡介
2、HTML 轉 PDF 之 wkhtmltopdf 工具精講
3、wkhtmltopdf參數詳解
4、解決wkhtmltopdf支持中文和縮放問題:wkhtmltopdf折騰記
與之類似的還有一個叫Phantomjs的插件,效果差不多,還沒深入研究。
---------------------
作者:dannyhoo6688
來源:CSDN
原文:https://blog.csdn.net/huyuyang6688/article/details/79710704
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!