婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > HTML轉PDF的純客戶端和純服務端實現方案

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

熱門標簽:長春極信防封電銷卡公司 強訊外呼系統 crm外呼系統好不好 電銷外呼線路改不外呼線路 重慶人工智能電銷機器人報價 愛巢地圖標注 貴陽ai外呼系統 智能電銷機器人廣告語 電話機器人批發

需求

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

解決思路

服務端生成

思路

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

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

服務端生成核心代碼

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

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

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

// html2pdf.js

const 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內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關文章,希望大家以后多多支持腳本之家!

標簽:內蒙古 保定 清遠 廣安 山南 陜西 吳忠 上海

巨人網絡通訊聲明:本文標題《HTML轉PDF的純客戶端和純服務端實現方案》,本文關鍵詞  HTML,轉,PDF,的,純,客戶端,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《HTML轉PDF的純客戶端和純服務端實現方案》相關的同類信息!
  • 本頁收集關于HTML轉PDF的純客戶端和純服務端實現方案的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    久久99久久久欧美国产| 国产剧情一区在线| 亚洲资源在线观看| 精品久久久三级丝袜| 亚洲视频在线观看三级| 蜜桃久久久久久| 欧美大胆人体bbbb| 老司机午夜精品| 精品精品国产高清一毛片一天堂| 国产精品成人一区二区艾草| 三级亚洲高清视频| 日韩一区二区三区免费看 | 欧美日韩一区二区三区四区 | 另类的小说在线视频另类成人小视频在线| 色综合久久88色综合天天6| 亚洲精品国产一区二区精华液 | 91美女片黄在线| 国产精品久久久久久福利一牛影视| 国产精品小仙女| 国产欧美一区二区精品性| 国产一区二区三区日韩| 一区二区三区影院| 欧美一区二区久久久| 国产在线乱码一区二区三区| 国产精品精品国产色婷婷| 91视频免费看| 激情六月婷婷综合| 亚洲国产一区视频| 欧美激情一区不卡| 欧美伦理影视网| 欧美日韩三级一区| 在线观看视频一区二区欧美日韩| 国产在线视频一区二区| 午夜成人在线视频| 亚洲图片欧美激情| 国产欧美精品一区二区三区四区 | 国产成人精品三级| 日本大胆欧美人术艺术动态| 中文字幕日韩欧美一区二区三区| 91精品国产全国免费观看| 色婷婷精品久久二区二区蜜臀av| 国产999精品久久久久久| 麻豆精品国产91久久久久久| 亚洲成人动漫精品| 亚洲一区二区偷拍精品| 亚洲欧美自拍偷拍| 日本一区二区三区免费乱视频 | 成人激情校园春色| 国产精品一区二区三区乱码| 国产精品主播直播| 日韩在线一区二区三区| 国产精品久久久久永久免费观看 | 国产精品日产欧美久久久久| 欧美二区三区的天堂| 欧美高清hd18日本| 日韩av电影免费观看高清完整版| 99精品在线免费| 成熟亚洲日本毛茸茸凸凹| 99精品偷自拍| 欧美日韩在线三级| 久久午夜国产精品| 中文字幕一区视频| 精品一区二区久久| 日韩欧美的一区| 欧美国产精品中文字幕| 亚洲一区在线观看网站| 国产精品一区二区久久不卡| 高潮精品一区videoshd| hitomi一区二区三区精品| 91精品国产91久久久久久最新毛片| 欧美三级日本三级少妇99| 成人性生交大片免费| 91精品国产福利| 亚洲成人免费观看| 91丨porny丨首页| 国产精品女同一区二区三区| 久久久久亚洲综合| 亚洲国产成人av好男人在线观看| 国产成人在线看| 8x福利精品第一导航| 亚洲狠狠爱一区二区三区| 色av一区二区| 亚洲精品高清在线| 国产综合久久久久影院| 麻豆91在线观看| 欧美日韩精品一区二区在线播放| 国产精品国产三级国产有无不卡| 91女人视频在线观看| 日韩久久精品一区| 亚洲精品欧美在线| 亚洲已满18点击进入久久| 91香蕉视频污| 亚洲欧美一区二区三区久本道91 | 国产精品乱码一区二三区小蝌蚪| 日韩高清欧美激情| 在线观看91精品国产入口| 精品粉嫩超白一线天av| 久久99国产精品成人| 777午夜精品免费视频| 亚洲综合区在线| 777午夜精品视频在线播放| 另类欧美日韩国产在线| 中文一区一区三区高中清不卡| 色屁屁一区二区| 亚洲色图制服诱惑 | 强制捆绑调教一区二区| xnxx国产精品| 国产69精品久久99不卡| 亚洲激情一二三区| 日韩欧美中文字幕制服| 99久久国产综合色|国产精品| 一区二区国产视频| 欧美成人免费网站| 懂色av一区二区三区蜜臀| 亚洲一区二区三区四区五区黄 | 一级做a爱片久久| 欧美午夜片在线看| 不卡区在线中文字幕| 人人爽香蕉精品| 国产日韩欧美精品电影三级在线| 色婷婷精品大在线视频| 激情综合色丁香一区二区| 国产精品女人毛片| 久久久国产午夜精品| 欧美aⅴ一区二区三区视频| 国产精品美日韩| 欧美男同性恋视频网站| 国产白丝精品91爽爽久久| 日韩—二三区免费观看av| 亚洲人精品午夜| 欧美mv日韩mv国产| 欧美午夜精品电影| 福利一区二区在线| 久久精品网站免费观看| 久久久久国产成人精品亚洲午夜| 欧美三级资源在线| 一区二区不卡在线播放 | 欧美日韩一区久久| 91麻豆文化传媒在线观看| 国产高清在线精品| 老司机午夜精品| 亚洲午夜久久久久久久久久久| 蜜臀av性久久久久av蜜臀妖精| 中文字幕欧美区| 久久久三级国产网站| 日韩精品一区二区三区在线观看| 色吊一区二区三区| 91视频观看视频| 亚洲欧美综合在线精品| 国产传媒欧美日韩成人| 黄页网站大全一区二区| 91视频免费看| 午夜亚洲国产au精品一区二区| 一区二区三区日韩| 亚洲在线视频网站| 亚洲欧美综合在线精品| 欧美日韩欧美一区二区| 久草精品在线观看| 亚洲一区二区三区小说| 一区二区三区在线视频播放 | 亚洲精品在线网站| 91精品欧美综合在线观看最新| 日本久久一区二区三区| 99国产精品一区| 色先锋aa成人| 欧美最新大片在线看| 色天天综合久久久久综合片| 亚洲五月六月丁香激情| 国产精品一区二区在线观看不卡| 日韩欧美aaaaaa| 久久精品国产**网站演员| 国产麻豆视频精品| 国产成人在线视频网站| 韩国v欧美v亚洲v日本v| 在线免费av一区| 777午夜精品视频在线播放| 国产精品高潮呻吟| 国内精品伊人久久久久av影院| 国产成人免费视频精品含羞草妖精| 亚洲男人的天堂在线aⅴ视频| 国产精品伦理在线| 国模一区二区三区白浆| 蜜臀久久99精品久久久久久9| 91福利在线看| 在线成人午夜影院| 欧美一级高清片在线观看| 91久久精品一区二区三区| 日韩女优av电影| 麻豆国产91在线播放| 国产在线播放一区| 精品在线视频一区| 国产精品国产三级国产aⅴ中文 | 国产成人精品影院| 91麻豆精品国产91久久久久久久久 | 久久久影视传媒| 国产成人免费视频一区| 精品国产一区二区国模嫣然| 午夜成人免费视频| 久久99精品国产麻豆婷婷洗澡| 欧美久久久久久蜜桃|