带中文的网页下载为PDF格式的文件(jsPDF)
1、調研
? ? ? ? ? 主要需要用到插件jsPDF,jsPDF可以將html下載為pdf格式的文件,但無法支持中文字形,下載帶中文的網頁會有亂碼,經驗證可以通過如下3種方案下載中文網頁。
2、方案
? ? ? ?2.1、方案一(jsPDF + html2canvas):html元素通過html2canvas生成canvas,再將canvas添加到pdf文檔上。
? ? ? ? ? ? ? ? ?優點: 文檔清晰度可控制,下載的PDF文件上不會有亂碼,html樣式還原度100%。
? ? ? ? ? ? ? ? ?缺點: 分頁不好控制,適合不長或者每頁內容比較規律(比如table數據)的頁面下載。
? ? ? ? ? ? ? ? ?項目下載jsPDF和html2canvas依賴,引入依賴,下面按不分頁與分頁的2種情況給出代碼示例。
? ? ? ? 2.1.1 不分頁
js源碼如下:
import { jsPDF } from 'jspdf'; import html2canvas from 'html2canvas'; let element = document.body; //下載整個頁面,也可以下載頁面的部分html let scale = 0.5; let pageFormat = [element.scrollWidth * scale, element.scrollHeight * scale]; const pdf = new jsPDF({orientation: 'l',unit: 'pt', // pdf大小計量單位format: pageFormat // 自定義第一頁pdf頁面大小,按html元素的比例設定 }); let opt = {scale: 4 // 保證pdf文檔內容清晰度,放大4倍,網上說這種方案文檔清晰度不高,經驗證可以這么解決清晰度問題 }; let width = pageFormat[0]; let height = pageFormat[1]; // 將html元素繪制為cancas html2canvas(element, opt).then(canvas => {// cancas添加到pdf文檔上pdf.addImage(canvas, 0, 0, width, height);// 下載pdf.save('下載' + '.pdf'); });? ? ? ?2.1.2 分頁
? ? ? ? ? ? ? ? html:提前規劃每月pdf內容
<div v-for="(data, index) in pageData" :key="index" :ref="'page' + index" class="pdf-page">第{{ index + 1 }} 頁...... </div>? ? ? ? ? ?? ? ? ?js代碼:將每一塊的html轉化為canvas,再將canvas添加到pdf的一頁上
// pageCount: 總共的頁數if (this.pageCount === 0) return;let elScale = 0.5;// 將每一塊的html轉化為canvas,再將canvas添加到pdf的一頁上let canvasPage = (pdf, index) => {let element = this.$refs['page' + index][0];let width = element.scrollWidth * elScale;let height = element.scrollHeight * elScale;html2canvas(element, { scale: 4 }).then(canvas => {(index > 0) && pdf.addPage();pdf.addImage(canvas, 0, 0, width, height);if ((index + 1) === this.pageCount) {pdf.save('demp.pdf');return;}index++;canvasPage(pdf, index);});};const pdf = new jsPDF({orientation: 'p', unit: 'pt', format: 'a4'});this.$nextTick(() => {canvasPage(pdf, 0);});}? ? ? ?2.2、方案二(jsPDF添加ttf中文字形文件)
? ? ? ? ? ? ? ? ?優點:pdf文檔可以自動分頁。
? ? ? ? ? ? ? ? ?缺點:需要保證帶中文的html元素的字體(font-family)和新添加的ttf文件字體一致,不然中文也為亂碼,會和你用的插件字體有沖突(比如你用到了iconfont),html中如果有圖片會無法下載成功。
? ? ? ? ? ? ? ? ?步驟如下:
? ? ? ? ? ? ? ? a、下載ttf文件。
? ? ? ? ? ? ? ? b、通過jsPDF提供的網頁將ttf文件轉為js文件(文件較大),網頁地址:https://rawgit.com/MrRio/jsPDF/master/fontconverter/fontconverter.html,轉化后的js文件內容如下:
? ? ? ? ? ? ? ? c、將font字符串復制粘貼到json文件(js文件內容很大,最好用記事本打開會快一些),放在前端項目的文件夾下,通過http請求json文件內容(不直接引入js文件,因為字體文件很大,直接引入node會報錯)。
? ? ? ? ? ? ? ? ?d、示例使用的ttf文件和json文件下載地址:https://download.csdn.net/download/buler_sky/15417402。
? ? ? ? ? ? ? ? ?e、html元素修改字體:style="font-family:chinese"。
? ? ? ? ? ? ? ? ?f、項目下載jsPDF和axios依賴(或者其他可以發送請求的插件),引入依賴,js源碼如下:?
import { jsPDF } from 'jspdf'; import axios from 'axios'; axios.get('/jspdf/chinese.json').then(res => {var callAddFont = function () {this.addFileToVFS('chinese.ttf', res.data.font);this.addFont('chinese.ttf', 'chinese', 'normal');};jsPDF.API.events.push(['addFonts', callAddFont]);download(jsPDF); }); download(jsPDF) {let element = document.body; //下載整個頁面,也可以下載頁面的部分htmllet pdf = new jsPDF({orientation: 'l',unit: 'pt',format: 'a4',compress: true});pdf.setFont('chinese');pdf.setFontSize(14);let pWidth = pdf.internal.pageSize.width; // 595.28 is the width of a4let srcWidth = element.scrollWidth;let margin = 18; // narrow margin - 1.27 cm (36);let scale = (pWidth - margin * 2) / srcWidth;pdf.html(element, {x: margin,y: margin,html2canvas: {scale: scale},callback: function (doc) {doc.save();}}); }? ? ? ? 2.3、?方案三(jsPdf + jsPDF-CustomFonts-support)
? ? ? ? ? ? ? ? ? ?優點: 示例為非包管理的項目、和方案二原理差不多,都是替換字體源,引入很簡單;
? ? ? ? ? ? ? ? ? ?缺點:?對應jsPDF版本比較老、和jsPdf文檔的api很多都不一致
? ? ? ? ? ? ? ? ? ?a、通過script引入插件:? ? ??
? ? ? ? ? ? ? ? ? <script?src="/jspdf/jspdf.es.min.js"></script>?
? ? ? ? ? ? ? ? ? <script?src="/jspdf/jspdf.customfonts.min.js"></script>?
? ? ? ? ? ? ? ? ? ?<script?src="/jspdf/default_vfs.js"></script>?
? ? ? ? ? ? ? ? ? ?b、js代碼:
let element = document.body; //下載整個頁面,也可以下載頁面的部分htmlconst doc = new jsPDF({format: 'a4'});doc.addFont('NotoSansCJKtc-Regular.ttf', 'NotoSansCJKtc-Regular', 'normal');doc.setFont('NotoSansCJKtc-Regular');console.log(doc.getFont());//最新的jsPdf的api為doc.html()doc.addHTML(element , {callback: function (doc) {doc.save();},x: 10,y: 10,margin: 10});? ? ? ? ? ? ?c、示例文件下載地址:https://download.csdn.net/download/buler_sky/15501445。
?3、總結
? ? ? ? ? ?1、尋找方法的過程中淘汰的方法:
? ? ? ? ? ? ? ? 方案三和方案二的原理差不多,但是不適合通過包管理的項目,需要通過script引入插件,且對應jsPDF版本比較老。
? ? ? ? ? ?2、尋找最佳解決方案的過程中遇見很多坑,這里依然沒有完美的解決問題(pdf分頁不完美和背景圖片無法下載),后續有突破會繼續更新,大家在實踐過程中如果有問題歡迎留言討論。
? ? ??
? ? ? ? ? ? ? ? ? ? ? ? ??
?
總結
以上是生活随笔為你收集整理的带中文的网页下载为PDF格式的文件(jsPDF)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CCNA培训(三)20210717day
- 下一篇: 大华解码器学习