亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > HTML > 正文

HTML轉PDF的純客戶端和純服務端實現方案

2024-08-26 00:14:05
字體:
來源:轉載
供稿:網友

需求

用戶填寫表單,點擊保存之后,可以直接下載pdf文檔。

解決思路

服務端生成

思路

谷歌瀏覽器在17年自行開發了Chrome Headless特性,并與之同時推出了 puppeteer,它可以被理解為是無界面但是可以完成服務器功能特性的瀏覽器。

所以我們可以在服務端啟動puppeteer瀏覽器,打開目標網址,使用chrome瀏覽器自帶的轉換功能進行html到pdf的轉換。

服務端生成核心代碼

首先要安裝puppeteer,npm安裝可能會出錯,最好使用cnpm淘寶鏡像安裝。

輸入 cnpm i puppeteer -S 安裝依賴。

創建一個js文件,只需要用puppeteer瀏覽器打開網址,保存pdf即可。

// html2pdf.jsconst puppeteer = require('puppeteer');(async function(){    // 啟動服務    const browser = await puppeteer.launch();    // 打開標簽頁    const page = await browser.newPage();    // 轉到該地址    await page.goto('https://koa.bootcss.com/#context');    // html頁面轉pdf并保存至path    await page.pdf({path:"test.pdf",format:'A4'})    // 關閉瀏覽器    await browser.close();})();

然后控制臺輸入 node html2pdf.js 啟動服務。

當然也可以module.export將模塊方法導出,根據業務邏輯來。

缺點

無法保存表單動態數據

由于是從服務端請求頁面,如果不在請求地址上保存用戶輸入,截出來的pdf將是頁面沒被填寫的初始狀態。

換而言之,他只能進行靜態頁面的轉換,因為我們的需求有大量用戶輸入,因此pass。

客戶端生成核心代碼

思路

  • 使用html2canvas,輸入需要轉換的dom節點,遍歷轉換成canvas畫布
  • 將canvas畫布轉成base64圖片,使用jsPDF創建pdf文件,把圖片插入進pdf。

缺點

失真。

我們可以很明顯的發現,既然是類似于對頁面截圖再將截圖插入pdf,頁面的分辨率和配置很可能影響輸出圖片的質量。

同時,因為是截圖,可能失去頁面鏈接等功能。

文字截斷

當canvas畫布大于pdf一頁大小時,輸出就會出錯,這時我們需要判斷canvas畫布是否超出A4大小,如果超出,對canvas進行分割,插入到不同的頁面。

這時候問題又來了,既然是分割圖片,那么很可能導致圖片或者文字從一半就被截斷,因為我們無法分析canvas內部item的結構。

核心代碼

我們的需求沒有圖片和鏈接,所以失真的問題對我們影響不大,同時我們的表單由多個重復等長的item組成,并且這些item都非常短,不會超出一張A4紙(雖然這樣不嚴謹,如果需要,你可以獲取DOM元素寬高,根據DOM元素高度裁剪)。

所以我打算直接根據item切分canvas,每個item給一頁A4紙保存。

在開始之前需要理解幾個核心方法:

html2canvas

   // DOM是要轉換的DOM節點    html2canvas(DOM,{        backgroundColor:"#ffffff",        width:width,        height:height,        scale:2,        allowTaint:true,    }).then((canvas)=>{        // canvas 是轉換成功后的畫布    })

jsPDF

   // 創建實例    let pdf = new jsPDF('','pt','a4');    // 將圖片添加到pdf文件里    // 第一個參數是待插入的文件(base64)格式,第二個是文件格式    // 第三第四是圖片左上角的坐標,最后兩個是圖片插入后的寬高    pdf.addImage(image,'JPEG',10,10,height,width);    // 添加新的一頁    pdf.addPage()    // 保存pdf文件    pdf.save()

canvas

  // canvas是待剪切的圖片    // sx,sy是開始裁剪的坐標    // swidth、sHeight是裁剪的寬高    // dx、dy是裁剪后圖像在canvas中插入的坐標    // sWidth,sHeight是裁剪后圖像在canvas中的寬高    cxt.drawImage(canvas,sx,sy,sWidth,sHeight,dx,dy,sWidth,sHeight);
/** * @description: 表單轉pdf文件 * @return: pdf */onSubmit(){    // 這是我要轉換的表單,里面有很多一樣的表格    let form = this.$refs.form;    // 獲取元素的寬高    let width = form.getBoundingClientRect().width;    let height = form.getBoundingClientRect().height;    html2canvas(form,{        backgroundColor:"#ffffff",        width:width,        height:height,        scale:2,        allowTaint:true,    }).then((canvas)=>{        let pdf = new jsPDF('','pt','a4');        // 進行圖片切割        let canvasList = this.splitCanvas(canvas,this.forms.length);        // 遍歷canvas列表,每頁添加一張圖片        canvasList.forEach((item,index)=>{            // 轉換圖片格式為base64            let itemImage = item.toDataURL('image/jpeg',1.0);            // 預留10px邊距,A4紙的寬在72分辨率的顯示器上是595px            pdf.addImage(itemImage,'JPEG',10,10,575.28,575.28/item.width*item.height);            // 如果不是最后一頁,則分頁            index == this.forms.length-1 ? '' : pdf.addPage();        })        // 文件保存        let blob = pdf.output('blob');                pdf.save('test.pdf');    })},/** * @description: 對canvas進行切割 * @param {number} num 切片數量  * @param {canvas} canvas  * @return {array} canvas列表 */splitCanvas(canvas,num){    let height = canvas.height,width = canvas.width;    let chunkHeight = height/num;// 每個切片的高度    let chunkList = [];// 存放結果canvas    for(let i=0; i<height ; i+=chunkHeight){        // 初始化裁剪矩形框位置        let sx = 0,sy = i,sWidth = width,sHeight = chunkHeight,dx = 0, dy = 0;        // 創建一個canvas節點        let canvasItem =document.createElement("canvas");        // 初始化畫布大小        canvasItem.height = chunkHeight;        canvasItem.width = width;        let cxt = canvasItem.getContext("2d");        // 將裁剪的圖片放到新的canvas節點        cxt.drawImage(canvas,sx,sy,sWidth,sHeight,dx,dy,sWidth,sHeight);        chunkList.push(canvasItem);     }    return chunkList;},

最終效果

表單保存后的頁面

轉換成pdf的效果

 到此這篇關于HTML轉PDF的純客戶端和純服務端實現方案的文章就介紹到這了,更多相關HTML轉PDF內容請搜索武林網以前的文章或繼續瀏覽下面的相關文章,希望大家以后多多支持武林網!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日本久久亚洲电影| 久久91亚洲精品中文字幕奶水| 热久久美女精品天天吊色| 成人精品久久av网站| 色老头一区二区三区在线观看| 91av网站在线播放| 国产精品成人va在线观看| 久久久久久香蕉网| 欧美wwwxxxx| 九九久久精品一区| 九九视频这里只有精品| 国产欧亚日韩视频| 国产精品久久久久久久久久尿| 91精品成人久久| 日韩免费电影在线观看| 正在播放亚洲1区| 日韩免费av在线| 91香蕉嫩草神马影院在线观看| 国产精品第8页| 一区二区三区高清国产| 2020久久国产精品| 国产成人久久久精品一区| 国产成人aa精品一区在线播放| 国产精品久久77777| 裸体女人亚洲精品一区| 色偷偷av亚洲男人的天堂| 久久91精品国产| 日韩av最新在线观看| 日韩电影在线观看永久视频免费网站| 日本精品视频在线观看| 国产亚洲精品久久久久久| 亚洲精品电影在线观看| 中文字幕视频一区二区在线有码| 久久久国产精品免费| 中文字幕亚洲图片| 成人性生交大片免费观看嘿嘿视频| 欧美国产日韩精品| 亚洲人免费视频| 国产精品麻豆va在线播放| 亚洲视频专区在线| 国产精品亚洲一区二区三区| 中文字幕无线精品亚洲乱码一区| 中文欧美日本在线资源| 精品偷拍一区二区三区在线看| 清纯唯美日韩制服另类| 精品国产一区二区三区久久久狼| 久久国产精品影视| 国产欧美在线播放| 中文字幕日本精品| 久久久久久尹人网香蕉| 欧美成年人视频网站欧美| 最近2019好看的中文字幕免费| 久久久女女女女999久久| 国产日韩欧美在线视频观看| 欧美麻豆久久久久久中文| www.日韩av.com| 亚洲视频视频在线| 精品二区三区线观看| 亚洲精品日韩av| 国产精品av在线播放| 欧美日韩中文在线| 一本久久综合亚洲鲁鲁| 欧美精品一二区| 欧美亚洲国产精品| 51视频国产精品一区二区| 日韩精品在线免费| 日韩中文娱乐网| 色狠狠av一区二区三区香蕉蜜桃| 97视频在线观看网址| 国产精品亚发布| 国产91网红主播在线观看| 国产精品久久久久久久久久久久久久| 午夜精品久久久久久久久久久久久| 久久天天躁狠狠躁夜夜躁2014| 国产亚洲免费的视频看| 亚洲国产欧美久久| 色香阁99久久精品久久久| 日韩在线精品一区| 欧美午夜激情视频| 麻豆乱码国产一区二区三区| 欧美日韩美女在线| 韩国三级电影久久久久久| 欧美超级免费视 在线| 国产一区二区在线免费| 色妞在线综合亚洲欧美| 亚洲综合一区二区不卡| 热久久免费国产视频| 高清欧美一区二区三区| 亚洲精品第一国产综合精品| 国产精品美女久久久久av超清| 欧美黄色成人网| 国产精品第三页| 一本色道久久综合狠狠躁篇的优点| 欧美日韩午夜视频在线观看| 97人人爽人人喊人人模波多| 亚洲中国色老太| 色琪琪综合男人的天堂aⅴ视频| 久久久久久91香蕉国产| 亚洲国产一区自拍| 国产a级全部精品| 久久久久久久久久国产精品| 91久久精品国产91久久性色| 国产成人精品一区二区在线| 国产精品爱久久久久久久| 欧美激情免费在线| 亚洲2020天天堂在线观看| 精品自拍视频在线观看| 97在线视频国产| 成人两性免费视频| 伊人伊成久久人综合网站| 久久精品国产v日韩v亚洲| 日韩av在线精品| 91国偷自产一区二区三区的观看方式| 成人免费在线网址| 影音先锋欧美精品| 国内精品久久久久伊人av| 国产精品视频区1| 亚洲欧美另类人妖| 成人免费视频在线观看超级碰| 欧美天天综合色影久久精品| 精品久久久久久中文字幕大豆网| 亚洲小视频在线观看| 日本欧美国产在线| 国产精品久久久久aaaa九色| 中文字幕v亚洲ⅴv天堂| 中文字幕欧美日韩va免费视频| 国产精品网红福利| 国产91对白在线播放| 中文欧美日本在线资源| 欧美精品激情在线| 国产精品偷伦免费视频观看的| 亚洲伊人成综合成人网| 欧美视频国产精品| 日韩av在线一区| 国产精品色午夜在线观看| 亚洲精品一区久久久久久| 国产在线播放不卡| 欧美日韩国产综合新一区| 亚洲欧美精品一区| 91久久精品国产91久久| 日韩高清中文字幕| 国产成人亚洲精品| 色妞色视频一区二区三区四区| 77777亚洲午夜久久多人| 日韩成人中文字幕| 久久久久久久影视| 国产视频久久久久| 97av在线视频| 国产福利精品在线| 国产精品海角社区在线观看| 自拍偷拍亚洲一区| 午夜精品理论片| 亚洲精品美女久久久| 亚洲美女动态图120秒| 久久人人爽人人爽爽久久| 国产精品久久久久久久久久尿| 亚洲成人av中文字幕| 中文字幕av一区中文字幕天堂| 欧美一级淫片丝袜脚交| 久久久久久久电影一区| 成人动漫网站在线观看| 亚洲第一免费播放区| 2019中文字幕在线| 国产91九色视频|