在許多生成報表的時候需要我們后台作出動態的數據,並渲染到前端生成pdf格式,Excel格式的各種報表,但是瀏覽器自帶的生成pdf功能,windows系統的ctrl+p鍵就能完全搞定這一需求,但對客戶來說,這種體驗極差,肯定是不行的,有好幾種方法將html生成pdf格式,每一種方法都有自己的優缺點,

先簡單談一談第一種比較簡單的jsPDF,代碼完全有javascript就夠了,不需要后台,但是不管哪一種都需要頁面前端代碼寫的表准規范,不那么亂套就行,
jsPDF:直接上代碼:
<!DOCTYPE html>
<html>
<head>
<title>jsPDF</title>
<meta charset="utf-8">
<script src="https://cdn.bootcss.com/html2canvas/0.5.0-beta4/html2canvas.js"></script>
<script src="https://cdn.bootcss.com/jspdf/1.3.4/jspdf.debug.js"></script>
<script type="text/javascript">
function htmltopdf() {
var target = document.getElementsByClassName("report")[0];
target.style.background = "#ffffff";
html2canvas(target, {
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;
//頁面偏移
var position = 0;
//a4紙的尺寸[595.28,841.89],html頁面生成的canvas在pdf中圖片的寬高
var imgWidth = 570.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("test.pdf");
}
})
}
</script>
<style type="text/css">
.report{width: 80%;height: 500px;margin: auto;}
</style>
</head>
<body>
<div class="report">
<h2>jspdf生成PDF</h2>
<button onclick="htmltopdf()">點擊生成pdf</button>
<table border="1" cellspacing="0">
<thead>
<tr>
<th align="center">調研對象</th>
<th align="center">優點</th>
<th align="center">缺點</th>
<th align="center">分頁</th>
<th align="center">圖片</th>
<th align="center">表格</th>
<th align="center">鏈接</th>
<th align="center">中文</th>
<th align="center">特殊字符、樣式</th>
<th align="center">導出樣例</th>
<th align="center">備注</th>
</tr>
</thead>
<tbody><tr>
<td align="center">jsPDF</td>
<td align="center">1、整個過程在客戶端執行(不需要服務器參與),調用簡單</td>
<td align="center">1、生成的pdf為圖片形式,且內容失真</td>
<td align="center">支持</td>
<td align="center">支持</td>
<td align="center">支持</td>
<td align="center">不支持</td>
<td align="center">支持</td>
<td align="center">支持</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">iText</td>
<td align="center">1、功能基本可以實現,比較靈活2、生成pdf質量較高</td>
<td align="center">1、對html標簽嚴;格,少一個結束標簽就會報錯;2、后端實現復雜,服務器需要安裝字體;3、圖片渲染比較復雜(暫時還沒解決)</td>
<td align="center">支持</td>
<td align="center">支持</td>
<td align="center">支持</td>
<td align="center">支持</td>
<td align="center">支持</td>
<td align="center">支持</td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">wkhtmltopdf</td>
<td align="center">1、調用方式簡單(只需執行一行腳本);2、生成pdf質量較高</td>
<td align="center">1、服務器需要安裝wkhtmltopdf環境;2、根據網址生成pdf,對於有權限控制的頁面需要在攔截器進行處理</td>
<td align="center">支持</td>
<td align="center">支持</td>
<td align="center">支持</td>
<td align="center">支持</td>
<td align="center">支持</td>
<td align="center">支持</td>
<td align="center"></td>
<td align="center"></td>
</tr>
</tbody></table>
</div>
</body>
</html>
網頁呈現下面樣式:

點擊按鈕執行js生成:

但這種方式有很大的缺點,分頁時會出現比較大的瑕疵,整體像素低,看起來不是特別的清晰
整體來說是截取的部分html代碼,下圖獲取元素為要截取的div,必須與后邊保持一致,此外還需外部導入js,這種方式使用canvas相當於將html頁面截屏保存成圖片放入pdf當中,謹慎使用。

下篇繼續寫wkhtmltopdf吧
