在許多生成報表的時候需要我們后台作出動態的數據,並渲染到前端生成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吧