前端實現(xiàn)HTML轉(zhuǎn)PDF下載的兩種方式

將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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末昌屉,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子茵瀑,更是在濱河造成了極大的恐慌间驮,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瘾婿,死亡現(xiàn)場離奇詭異蜻牢,居然都是意外死亡烤咧,警方通過查閱死者的電腦和手機偏陪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來煮嫌,“玉大人笛谦,你說我怎么就攤上這事〔ⅲ” “怎么了饥脑?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵恳邀,是天一觀的道長。 經(jīng)常有香客問我灶轰,道長谣沸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任笋颤,我火速辦了婚禮乳附,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘伴澄。我一直安慰自己赋除,他們只是感情好,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布非凌。 她就那樣靜靜地躺著举农,像睡著了一般。 火紅的嫁衣襯著肌膚如雪敞嗡。 梳的紋絲不亂的頭發(fā)上颁糟,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天,我揣著相機與錄音秸妥,去河邊找鬼滚停。 笑死,一個胖子當著我的面吹牛粥惧,可吹牛的內(nèi)容都是我干的键畴。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼突雪,長吁一口氣:“原來是場噩夢啊……” “哼起惕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起咏删,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤惹想,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后督函,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嘀粱,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年辰狡,在試婚紗的時候發(fā)現(xiàn)自己被綠了锋叨。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡宛篇,死狀恐怖娃磺,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情叫倍,我是刑警寧澤偷卧,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布豺瘤,位于F島的核電站,受9級特大地震影響听诸,放射性物質(zhì)發(fā)生泄漏坐求。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一晌梨、第九天 我趴在偏房一處隱蔽的房頂上張望瞻赶。 院中可真熱鬧,春花似錦派任、人聲如沸砸逊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽师逸。三九已至,卻和暖如春豆混,著一層夾襖步出監(jiān)牢的瞬間篓像,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工皿伺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留员辩,地道東北人。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓鸵鸥,卻偏偏與公主長得像奠滑,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子妒穴,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容