背景
昨天產品經理找我,說現在下載簡歷的功能,下載到的簡歷和ui的不一樣,希望做成一樣的。我的第一反應就是說那我們給后端寫個靜態頁面,后端把相應的字段套進去吧。產品又說,每個渠道的簡歷的樣式都不一樣,不節能每個渠道都有對應的一個簡歷的靜態頁面,這樣太復雜。希望通過前端下載,即前端直接保存簡歷預覽頁到本地。其實,一開始我是拒絕的,但是最后想想,寫這么多靜態頁面也麻煩,索性就嘗試嘗試來解決這個問題吧。
初定技術方案
拿到這個需求之后,在網上查找了相關的資料。初步有兩個方案。
- 通過
html2canvas
生成圖片,然后再利用 jsPDF
將圖片導入pdf並保存。
- 通過
html2canvas
生成圖片,使用 FileSaver
將圖片導入保存文件 。
對比了一下這兩種技術方案,應該都能滿足使用。
並且從瀏覽器兼容性的角度去看,方案一使用到ArrayBuffer這個類,方案二使用到Bolb類,都只能兼容到ie10。然后由於我們這個的需求為保存PDF文件,所以我就選了 jsPDF
這個庫作為該方案的解決方案,感覺它專門針對pdf的,顯得更專業點。
小試牛刀
確定了技術方案,那就按照定好的技術方案來執行,根據官方給的demo先寫一段代碼實現一下基礎功能,看效果如何,代碼如下:
import html2canvas from "html2canvas";
import * as jsPDF from "jspdf";
html2canvas(dom).then(canvas => {
var imgData = canvas.toDataURL('image/jpeg');
var doc = new jsPDF("p", "mm", "a4");
doc.addImage(imgData, 'JPEG', 0, 0,210,297);
doc.save(pdfName + ".pdf");
})
這段代碼很簡單,相信大家也都能看懂。試了一下,確實能生成對應名稱的文件名。打開文件一看,感覺有點模糊。。。客戶下載簡歷是需要投遞給hr的,那可不能模糊啊。這個問題需要解決,一定要解決的!!!
解決pdf模糊的問題
上文中也提到了,代碼很簡單,模糊無非就兩種情況嘛,一種canvas到的圖片模糊,另外一種是保存pdf的時候模糊了。那我們就一步步試驗排除一下吧。然后把圖片的 DOMString
打印一下,放到瀏覽器看一下,發現圖片有點模糊,那么問題定位到了,就想辦法解決吧。
首先,我想到了 canvas.toDataURL
的api有一個默認圖片質量的參數,如果不填,則是0.92。之前寫過一篇壓縮上傳的圖片就是通過這個參數壓縮的。那就把它改成1吧。該api的詳細文檔,參見 文檔 。再到瀏覽器里看看圖片,發現有點效果,但是還是模糊。當然,這個也可能是我的肉眼的問題。還得繼續解決啊。
然后在官方github上找到了一個關於清晰度的pr,連接如下: 我是修改清晰度pr , 增加了scale和dpi參數,可以設置畫布的dpi,canvas默認的dpi是96dpi,scale默認為1。當兩者同時存在時,以scale為主,會忽略dpi。
清晰度的問題解決了,那么是不是大功告成了呢?開始我也這樣認為的,並且也測試着下載了幾個簡歷,完美!但是,我發現當簡歷數據內容很多的時候,下載的pdf字體被壓扁了。我簡單了分析了一下,懷疑是圖片太高,插入一頁pdf,如果圖片的高度大於pdf的高度,是不是會強行的把圖片壓縮成pdf的高度呢?那怎么辦呢?我們可不可以給pdf做個分頁呢?
分頁解決字體壓扁問題
既然想到了用分頁,那么就搜索了一下jsPDF分頁的內容。發現它有一個 addPage
的函數,那就簡單了。我們可以計算出canvas的高度,已知a4紙的高度,如果大於,就需要分頁,使用addPage函數。這里也是有兩種解決方案,當然,這兩個方案都不是我自己寫的,哈哈哈。
方案一
該方案使用的關鍵技術就是canvas的 drawImage
api,把一個長圖按照pdf的高度截取出好多個短圖,然后插入對應的頁面。這個原作者寫的博客,使用到了遞歸。原博客 ,作者已經把代碼帖進去了,我看了一下,然后使用了一下發現是可以用的。
方案二
方案二使用的關鍵技術是jsPDF的 addImage
的頁面偏移的位置和jsPD超出內容不顯示的特性。其實理解起來也很簡單,第一頁我插入canvas的偏移位置為0,第二頁偏移位置就是一個a4紙的高度,第三頁就是兩個a4紙的高度,以此類推。原博客 ,作者已經把代碼帖進去了,我看了一下,然后使用了一下發現是可以用的。
當時我還想,同時插入這么多canvas會不會使pdf文件的體積變大,后來看了看,測試下來,發現並不會,那個人推薦第二種方案,因為代碼少,好理解。看方案一的代碼,也看了一會兒才看明白,哈哈。
好了,寫到這里,基本上使用javascript把html轉成pdf下載就寫完了,最后還是要感謝上文中提到的連接。
本人博客地址, 最近搞了一個非常簡單的工時管理小程序,大佬們可以提提建議。
