1. 程式人生 > 其它 >js取iframe 上級頁面_pdf.js實戰,含水印、電子簽章解決方案

js取iframe 上級頁面_pdf.js實戰,含水印、電子簽章解決方案

技術標籤:js取iframe 上級頁面

專案涉及到移動端檢視電子合同的問題,前前後後試了三種方案,真是一步一個坑,三種方案各有各的優點,不水,直接上程式碼,按照自己的需求選擇。

一、pdf-vue

直接使用vue-pdf外掛,核心的程式碼是pdf.js,只不過就是自己封裝了一下,優點是方便快捷,缺點是無法載入電子簽章。

github地址

https://github.com/FranckFreiburger/vue-pd f#readme

1、npm install pdf-vue --save

2、template程式碼

  
class="pdf" v-show="fileType === 'pdf'">

class

="arrow"> // 上一頁 "changePdfPage(0)" class="turn" :class="{grey: currentPage==1}">Preview {{currentPage}} / {{pageCount}} // 下一頁 "changePdfPage(1)" class="turn" :class="{grey: currentPage==pageCount}">Next // 自己引入就可以使用,這裡我的需求是做了分頁功能,如果不需要分頁功能,只要src就可以了
:src="src" // src需要展示的PDF地址 :page="currentPage" // 當前展示的PDF頁碼 @num-pages="pageCount=$event" // PDF檔案總頁碼 @page-loaded="currentPage=$event" // 一開始載入的頁面 @loaded="loadPdfHandler"> // 載入事件

3、js程式碼

import pdf from 'vue-pdf'export default {    components: {pdf},
data () { return { currentPage: 0, // pdf檔案頁碼 pageCount: 0, // pdf檔案總頁數 fileType: 'pdf', // 檔案型別     src: '', // pdf檔案地址 } },  created: {    // 有時PDF檔案地址會出現跨域的情況,這裡最好處理一下    this.src = pdf.createLoadingTask(this.src)  } method: { // 改變PDF頁碼,val傳過來區分上一頁下一頁的值,0上一頁,1下一頁 changePdfPage (val) { // console.log(val) if (val === 0 && this.currentPage > 1) { this.currentPage-- // console.log(this.currentPage) } if (val === 1 && this.currentPage < this.pageCount) { this.currentPage++ // console.log(this.currentPage) } }, // pdf載入時 loadPdfHandler (e) { this.currentPage = 1 // 載入的時候先載入第一頁 } }}

使用非常方便,尤其是隻需要翻頁,或者不需要翻頁的,強烈推薦。

二、pdf-dist

pdf-dist也是基於pdf.js的一個元件,只不過沒有封裝,需要自己配置,優點是可配置,可實現特殊的需求,缺點是需要自己封裝,水印可載入,網上說可以載入電子簽章,我的載入不出來,所以還是沒采用。

1、npm install pdf-dist --save

2、封裝一個pdf.vue

<template>  <div class="cpdf" id="cpdf">    <div class="center">      <canvas class="canvasstyle" id="the-canvas">canvas>      <div class="contor">        <button @click="prev" style="margin-right: 10px">上一頁button>        <span>Page: <span v-text="page_num">span> / <span v-text="page_count">span>span>        <button @click="next" style="margin-left: 10px">下一頁button>      div>    div>  div>template><script>import PDFJS from 'pdfjs-dist'export default {  name: 'c-pdf',  // 接收父元件傳來的引數  props: ['pdfurl'],  components: { },  data () {    return {      pdfDoc: null, // pdfjs 生成的物件      pageNum: 1, //      pageRendering: false,      pageNumPending: null,      scale: 1, // 放大倍數      page_num: 0, // 當前頁數      page_count: 0, // 總頁數      maxscale: 2, // 最大放大倍數      minscale: 0.8// 最小放大倍數    }  },  methods: {    renderPage (num) { // 渲染pdf      let vm = this      this.pageRendering = true      let canvas = document.getElementById('the-canvas')      let ctx = canvas.getContext('2d')      let bsr =                ctx.webkitBackingStorePixelRatio ||                ctx.mozBackingStorePixelRatio ||                ctx.msBackingStorePixelRatio ||                ctx.oBackingStorePixelRatio ||                ctx.backingStorePixelRatio ||                1      let dpr = window.devicePixelRatio || 1      let ratio = dpr / bsr      // Using promise to fetch the page      this.pdfDoc.getPage(num).then(function (page) {        var viewport = page.getViewport(screen.availWidth / page.getViewport(1).width)        // alert(vm.canvas.height)        canvas.height = ratio * viewport.width        canvas.width = ratio * viewport.height        canvas.style.width = 1.5 * viewport.width + 'px'        canvas.style.height = 1 * viewport.height + 'px'        ctx.setTransform(ratio, 0, 0, ratio, 0, 0)        // Render PDF page into canvas context        var renderContext = {          canvasContext: ctx,          viewport: viewport        }        var renderTask = page.render(renderContext)        // Wait for rendering to finish        renderTask.promise.then(function () {          vm.pageRendering = false          if (vm.pageNumPending !== null) {            // New page rendering is pending            vm.renderPage(vm.pageNumPending)            vm.pageNumPending = null          }        })      })      vm.page_num = vm.pageNum    },    addscale () { // 放大      if (this.scale >= this.maxscale) {        return      }      this.scale += 0.1      this.queueRenderPage(this.pageNum)    },    minus () { // 縮小      if (this.scale <= this.minscale) {        return      }      this.scale -= 0.1      this.queueRenderPage(this.pageNum)    },    prev () { // 上一頁      let vm = this      if (vm.pageNum <= 1) {        return      }      vm.pageNum--      vm.queueRenderPage(vm.pageNum)    },    next () { // 下一頁      let vm = this      if (vm.pageNum >= vm.page_count) {        return      }      vm.pageNum++      vm.queueRenderPage(vm.pageNum)    },    closepdf () { // 關閉PDF      this.$emit('closepdf')    },    queueRenderPage (num) {      if (this.pageRendering) {        this.pageNumPending = num      } else {        this.renderPage(num)      }    }  },  computed: {    ctx () {      let id = document.getElementById('the-canvas')      return id.getContext('2d')    }  },  mounted () {    let vm = this    PDFJS.getDocument(vm.pdfurl).then(function (pdfDoc_) { // 初始化pdf      vm.pdfDoc = pdfDoc_      vm.page_count = vm.pdfDoc.numPages      vm.renderPage(vm.pageNum)    })  }}script><style  lang="stylus" scoped>  .cpdf {    display: flex;    justify-content: center;    align-items: center;    .center {      text-align: center;      height: 100%;      overflow: hidden;      padding-top: 20px;      .contor {        position: fixed;        bottom: 30px;        left: 0;        width: 100%;        z-index: 99999;        font-size 30px        margin-top 20px        margin-bottom: 10px;      }    }  }style>

3、直接當成元件,引用就可以了

import cdpdf from '../../../components/pdf.vue':pdfurl="pdfurl">

一開始專案使用的是pdf-dist,因為後來電子簽章顯示不出來:

Warning: Unimplemented widget field type "Sig", falling back to base field type.

從網上搜了很多方法,說是需要修改pdf.work.js的原始碼,全域性搜尋AnnotationFlag.HIDDEN:

if(data.fieldType==='Sig') {    warn('unimplemented annotation type: Widget signature');    // 註釋下面這行程式碼    this.setFlags(AnnotationFlag.HIDDEN); }

可能是移動端使用微信瀏覽器的原因,註釋掉程式碼還是不好使,只能再想其他辦法了

三、pdf.js

最後用了最笨的辦法,直接從GitHub拉下來pdf.js的demo,用iframe標籤包住demo裡的HTML檔案,直接套著用,完美解決電子簽章的問題:

1、從GitHub拉一下原始碼,或者從這個地址直接下載

https://mozilla.github.io/pdf.js/getting_started/#download

下載下來以後放在public檔案下(3.x腳手架)

2、iframe標籤直接粗暴的設定src

 :style="{height: Height}" style="width: 100%">this.pdfUrl = '../pdf/web/viewer.html?file=' + this.pdfurl, +'PDF'pdfUrl是iframe標籤的URL,pdfurl是需要檢視的PDF檔案的url

總結

只要能實現需求的程式碼就是好程式碼,我的專案是移動端檢視PDF檔案,因為檔案上有電子簽章,所以嘗試了好幾種方案,個人還是推薦第二種方案,如果沒有電子簽章的情況下。

各位哥哥姐姐點個關注吧

1e18f8bbe87a7498d7fe661f6d8d1e2b.png