將HTML頁面轉(zhuǎn)化為PDF下載是前端經(jīng)常會遇到的需求宴偿,下面就列舉兩種方式進行實現(xiàn)。以下兩種方式默認都是在Vue項目環(huán)境下诀豁,其他框架項目自行靈活運用窄刘。
方式一:使用html2canvas和jspdf插件實現(xiàn)
該方式是通過html2canvas將HTML頁面轉(zhuǎn)換成圖片,然后再通過jspdf將圖片的base64生成為pdf文件舷胜。實現(xiàn)步驟如下:
1,下載插件模塊
npm install html2canvas jspdf --save
2,定義功能實現(xiàn)方法
在項目工具方法存放文件夾utils中創(chuàng)建htmlToPdf.js文件娩践,代碼如下:
// 導出頁面為PDF格式importhtml2Canvasfrom'html2canvas'importJsPDFfrom'jspdf'exportdefault{install(Vue,options){Vue.prototype.getPdf=function(){vartitle=this.htmlTitlehtml2Canvas(document.querySelector('#pdfDom'),{allowTaint:true}).then(function(canvas){letcontentWidth=canvas.widthletcontentHeight=canvas.heightletpageHeight=contentWidth/592.28*841.89letleftHeight=contentHeightletposition=0letimgWidth=595.28letimgHeight=592.28/contentWidth*contentHeightletpageData=canvas.toDataURL('image/jpeg',1.0)letPDF=newJsPDF('','pt','a4')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.89if(leftHeight>0){PDF.addPage()}}}PDF.save(title+'.pdf')})}}}
3, 全局引入實現(xiàn)方法
在項目主文件main.js中引入定義好的實現(xiàn)方法,并注冊烹骨。
importhtmlToPdffrom'@/components/utils/htmlToPdf'// 使用Vue.use()方法就會調(diào)用工具方法中的install方法Vue.use(htmlToPdf)
4, 在相關(guān)要導出的頁面中翻伺,點擊時調(diào)用綁定在Vue原型上的getPdf方法,傳入id即可
//html<divid="pdfDom">? <!-- 要下載的HTML頁面,頁面是由后臺返回 -->
? <divv-html="pageData"></div></div><el-button type="primary"size="small"@click="getPdf('#pdfDom')">點擊下載</el-button>//jsexportdefault{data(){return{htmlTitle:'頁面導出PDF文件名'}}}
方式二:讀取后臺返回文件流沮焕,利用HTML5中a標簽的download屬性實現(xiàn)下載
該方法需要先請求后臺吨岭,后臺會返回一個文件流,然后解析文件流峦树,再通過HTML5中<a>標簽的download屬性實現(xiàn)下載功能未妹。步驟如下:
1,發(fā)送請求簿废,獲取到后臺返回的文件流及文件信息
前端發(fā)送請求獲取下載文件信息:
// 引入下載方法import{download}from'utils'exportdefault{methods:{asyncdownloadFile(){letres=awaitaxios.get(url:'xxxx/xxxx',method:'GET',// 設(shè)置返回數(shù)據(jù)類型,這里一定要設(shè)置络它,否則下載下來的pdf會是空白,也可以是`arraybuffer`responseType:'blob',params:{id:'xxxxxx'})// 獲取在response headers中返回的下載文件類型lettype=JSON.parse(res.headers)['content-type']/*獲取在response headers中返回的下載文件名
? ? ? ? 因為返回文件名是通過encodeURIComponent()函數(shù)進行了編碼族檬,因此需要通過decodeURIComponent()函數(shù)解碼
? ? ? */letfileName=decodeURIComponent(JSON.parse(res.headers)['file-name'])// 調(diào)用封裝好的下載函數(shù)download(res,type,fileName)}}}
后臺返回的文件流格式:
2, 封裝下載方法 - 解析文件流,創(chuàng)建a標簽并設(shè)置下載相關(guān)屬性化戳。
// utils.jsexportconstdownload=(res,type,filename)=>{// 創(chuàng)建blob對象单料,解析流數(shù)據(jù)constblob=newBlob([res],{// 如何后端沒返回下載文件類型,則需要手動設(shè)置:type: 'application/pdf;chartset=UTF-8' 表示下載文檔為pdf点楼,如果是word則設(shè)置為msword扫尖,excel為exceltype:type})consta=document.createElement('a')// 兼容webkix瀏覽器,處理webkit瀏覽器中href自動添加blob前綴掠廓,默認在瀏覽器打開而不是下載constURL=window.URL||window.webkitURL// 根據(jù)解析后的blob對象創(chuàng)建URL 對象constherf=URL.createObjectURL(blob)// 下載鏈接a.href=herf// 下載文件名,如果后端沒有返回换怖,可以自己寫a.download = '文件.pdf'a.download=filename? document.body.appendChild(a)a.click()document.body.removeChild(a)// 在內(nèi)存中移除URL 對象window.URL.revokeObjectURL(herf)}
3,點擊下載按鈕蟀瞧,調(diào)用下載方法
<divid="pdfDom"><!-- 要下載的頁面 --><divv-html="pageData"></div></div><el-buttontype="primary"size="small"@click="downloadFile">點擊下載</el-button>
總結(jié)
以上兩種實現(xiàn)方式各有優(yōu)劣沉颂,方式一是純前端實現(xiàn),需要引入第三方插件悦污,可能會導致項目體積增加铸屉。方式二雖然更加簡潔,但a標簽的download屬性為HTML5新增屬性切端,可能存在兼容性問題彻坛。如果有需要,可以根據(jù)自己情況來選擇踏枣。
作者:桃花谷主V
鏈接:http://www.reibang.com/p/56680ce1cc97