將頁面dom導出為pdf格式並進行下載


1.使用npm下載兩個插件

a.將html頁面轉換成圖片
npm install --save html2canvas 
b.將圖片生成pdf
npm install jspdf --save

或者直接使用cdn

<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.5.0-alpha1/html2canvas.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.4/jspdf.min.js"></script> 

html部分

<template>
  <div class="">
    <div @click="downLoadPdf">下載pdf文件</div>
    <!--  -->
    <button type="button" class="btn btn-primary" v-on:click="getPdf()">導出PDF分頁</button>
    <div class="pdf_warp">
      <div id="pdfDom">
        <h1>vue項目中使用pdf.js預覽pdf文件(流)</h1>
        <p class="">
          好一段時間沒有來簡書寫東西了,因為來到了平安銀行(橙信)工作了,工作也比較忙,上班也沒得外網,最近公司給配置了一個mac電腦,終於可以有外網權限了,但還是有很多限制,微信,百度雲盤等等吧,都用不了,
          最近項目中需要顯示保險的電子保單,但給的地址是一個pdf文件流,遇到了各種問題,跨域、android手機打不開......,最終選擇了pdf.js插件,viewer.html?file=的形式打開,下面詳情介紹一下開發步驟,
          
        </p>
        <p>一、 首先是導入插件,從官網直接下載,鏈接:官網直接下載,在vue項目中,注意放在static文件目錄下</p>
        <div class="img_warp">
          <img src="../../../assets/4369687-c90a77c68fc6e04a.webp" alt="">
        </div>
        <p>簡單介紹一下pdf.js目錄,核心的pdf.js和pdf.worker.js,以及展示pdf的viewer.html頁面,把它們作為靜態資源來編譯,基本想要的build和web這兩個重要文件夾的東西都正常編譯。</p>
        <p>二、重點介紹一下viewer.html?file=打開pdf文件</p>
        <p>1、打開viewer.js看看</p>
        <div class="js_warp">
          <p>"use strict";</p>
          <p>var DEFAULT_URL = 'compressed.tracemonkey-pldi-09.pdf';</p>
          <p>var pdfjsWebApp = void 0;</p>
        </div>
        <p>里面有配置項,DEFAULT_URL 是默認的pdf路徑,繼續看源代碼,發現他可以通過file參數用來指定pdf的路徑</p>
        <p>用viewer.html?file= 的方式,我是iframe進行嵌套</p>
        <!-- <div class="js_warp">
          <p><iframe :src="url" width="100%" height="100%"></iframe></p>
        </div> -->
        <p>2、當viewer.html頁面的域和pdf文件域不一致的時候,會報 “file origin does not match viewer”錯誤。 所以我們得改變一下源碼</p>
        <div class="img_warp">
          <img src="../../../assets/cw1.webp" alt="">
        </div>
        <p>3、file=后面跟的pdf地址也有參數,所以必須選擇 encodeURIComponent 進行對url的編碼</p>
        <div class="js_warp">
          <p>this.url = `${baseUrl.pageRoot}pdf/web/viewer.html?file=${encodeURIComponent(pdfUrl)}`</p>
        </div>
        <p>viewer.js里有方法parseQueryString(query)取到這個pdf文件地址后,會進行decodeURIComponent解碼</p>
        <p>4、如果還是打不開pdf文件,pdf.js插件可能無法識別pdfUrl,所以的在最后加上 &.pdf 來騙過插件</p>
        <p>Q: 目前還遇到一個問題,GET請求pdfUrl時,cookie信息沒有帶給后端,目前是讓后端直接屏蔽了登錄驗證,請各位指教。GET請求源碼如下:</p>

        <h1>vue3基礎</h1>
        <h2>一、setup</h2>
        <p>1.setup函數可以被理解為函數的入口</p>
        <p>2.setup函數接收兩個參數:props、context(包含attrs、slots、emit)</p>
        <p>3.setup函數是處於生命周期函數 beforeCreate之前執行,執行setup函數時組件實例並未被創建,this不指向vue實例</p>
        <p>4.與模板一起使用:須在ref或reactive中聲明然后return出去使用才是響應式的</p>
        <p>5.使用渲染函數:可以返回一個渲染函數,該函數可以直接使用在同一作用域中聲明的響應式狀態</p>
        <h2>二、setup第一個參數props</h2>
        <p>props 是響應式的,當傳入新的 prop 時,它將被更新。</p>
        <div class="js_warp">
          <p>export default {</p>
          <p>props: {</p>
          <p>title: String</p>
          <p> },</p>
          <p>setup(props) {</p>
          <p>console.log(props.title)</p>
          <p>}</p>
          <p>}</p>
        </div>
        <h2>因為 props 是響應式的,不能使用 ES6 解構,會消除 prop 的響應性。</h2>
        <p>如果需要解構 prop,可以在 setup 函數中使用 [toRefs]函數來完成此操作:</p>
        <div class="js_warp">
          <p>setup(props) {</p>
          <p> const { title } = toRefs(props)</p>
          <p> return{ title  }</p>
          <p> },</p>
        </div>
        <h2>三、setup第二個參數context</h2>
        <p>context 是一個普通 JavaScript 對象,暴露了其它可能在 setup 中有用的值</p>
        <div class="js_warp">
          <p>setup(props, context) {</p>
          <p>// Attribute (非響應式對象,等同於 $attrs)</p>
          <p>console.log(context.attrs)</p>
          <p> // 插槽 (非響應式對象,等同於 $slots)</p>
          <p>console.log(context.slots)</p>
          <p>// 觸發事件 (方法,等同於 $emit)</p>
          <p>console.log(context.emit)</p>
          <p>// 暴露公共 property (函數)</p>
          <p>console.log(context.expose)</p>
          <p>}</p>
        </div>
        <h2>context不是響應的,可以用ES6進行解構</h2>

        <div ref="footer"></div>
      </div>
    </div>
 
  </div>
</template>
dom轉pdf-轉出內容

可以有兩種方式導出 

引入基礎模塊

import html2canvas from 'html2canvas'
import jsPDF from 'jspdf'
  data() { 
    return {
      htmlTitle: '頁面導出PDF文件名',  //這個也是固定寫法,pdf文件下載的名稱
  },

  1:第一種不分頁面

 methods:{
  // 下載pdf文件 不分頁
    downLoadPdf(){
        window.scrollTo(0, 0);  
        const element = document.querySelector('#pdfDom')  ;// 這個dom元素是要導出pdf的div容器
        setTimeout(() => { 
          html2canvas(element, {  
            height: this.$refs.footer.offsetTop,
            useCORS: true // 如果說所生成的頁面中帶有跨域的圖片,這個useCors需要設置為True 否則畫布被污染不會顯示
          }).then((canvas) => {
            console.log(canvas);
            const contentWidth = canvas.width;
            const contentHeight = canvas.height;
            // 一頁pdf顯示html頁面生成的canvas高度;
            const pdfX = (contentWidth + 100) / 2 //* 0.975;
            const pdfY =  (contentHeight + 100) / 2 //* 0.975;// 500為底部留白
            const imgX = pdfX;
            const imgY = (contentHeight / 2);// 內  * 0.75
            const pageData = canvas.toDataURL('image/png', 1.0);
            const pdf = new jsPDF('', 'pt', [pdfX, pdfY]);
            // 有兩個高度需要區分,一個是html頁面的實際高度,和生成pdf的頁面高度(841.89)
            // 內容未超過pdf一頁顯示的范圍,無需分頁
            pdf.addImage(pageData, 'png', 0, 0, imgX, imgY);
            pdf.save(12 + '.pdf'); // 生成的文件名字
          })
        },10)
    },
}

導出效果:

 

 

 

 2:第二種 導出pdf分頁

 methods:{
    
    // 下載pdf文件 分頁
    getPdf(){
      var title = this.htmlTitle
      html2canvas(document.querySelector('#pdfDom'), {
        allowTaint: true,
        useCORS: true
      }).then(function (canvas) {
        let contentWidth = canvas.width
        let contentHeight = canvas.height
        let pageHeight = contentWidth / 592.28 * 841.89
        let leftHeight = contentHeight
        let position = 0
        let imgWidth = 595.28
        let imgHeight = 580.28 / contentWidth * contentHeight
        let pageData = canvas.toDataURL('image/jpeg', 1.0)
        let PDF = new jsPDF('', '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.89
            if (leftHeight > 0) {
              PDF.addPage()
            }
          }
        }
        PDF.save(title + '.pdf')
      }
      )
    },
}

導出效果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM