vue中如何實現pdf檔案預覽?

sunxiaoying123發表於2019-03-04

今天產品提出一個優化的需求,就是之前我們做的圖片展示就是一個img標籤搞定,由於我們做的是海外後臺管理系統,那邊的人上傳的檔案時pdf格式,vue本事是不支援這種格式檔案展示的,於是就google搜尋,發現有iframe、embed、vueshowpdf(測試了不咋好用)、pdf等,本文說一下pdf外掛的使用過程。

  • 說明:iframe標籤這種,對於有的連結是可以的,比如這種連結在伺服器端沒有設定享有頭content-disposition,就可以直接顯示,如下:

vue中如何實現pdf檔案預覽?

想複製程式碼如下:

<iframe src="http://storage.xuetangx.com/public_assets/xuetangx/PDF/PlayerAPI_v1.0.6.pdf" width="100%" height="100%">
       This browser does not support PDFs. Please download the PDF to view it: <a href="/test.pdf">Download PDF</a>
</iframe>複製程式碼

顯示效果如下:

vue中如何實現pdf檔案預覽?

      如果pdf有很多頁,也不用考慮分頁功能,自動可以向下滑動就翻頁,看著挺好,但是,且往下繼續看----->

      我們把上邊的連結換成'https://ecs7.tokopedia.net/instant-loan/file/29a2218e-bef9-44cb-b92b-8e81bc4d5228_DOC-20171013-WA0035.pdf',發現什麼了?快看截圖。。。同樣是pdf連結,怎麼這個就不行?

vue中如何實現pdf檔案預覽?

什麼情況,下載框,必須下載才能看到,那多影響體驗,下到本地還佔我磁碟,不行不行,把上邊那個連線放到瀏覽器,回車看一下響應頭部:

content-disposition:attachment; filename="DOC-20171013-WA0035.pdf"

就是它,讓我們必須彈出下載框,由於這些檔案是在遠端伺服器上存貯著,想著讓後端看能不能檢測到這個響應頭,他們也懶得處理,後來只能自己處理了,鑑於這種情況,網上也是有很多解決辦法的,本人試驗過可以的。中間也是借用了一篇文章 ,根據自己需求,做了簡單的處理。

https://www.2cto.com/kf/201803/728492.html 
複製程式碼

過程如下:

  1. 執行npm install pdf-dist --save
  2. 在comments目錄下建立兩個檔案:pdf.vue 和 index.js

<!-- pdf.vue -->

<template>      <div id="container" :class="{'back': isShow}">      <canvas id="the-canvas"></canvas>      <!-- //新增關閉pdf功能 -->      <span :class="{'close':isShow}" @click="closePdf">close</span>      <p class="foot" v-if="pdfDoc">        <Button class="left" @click="onPrevPage" v-if="pageNum>1">上一頁</Button>        <Button class="right" @click="onNextPage" v-if="pageNum<pdfDoc.numPages">下一頁</Button>      </p>      </div>  </template><script>import PDFJS from 'pdfjs-dist' export default {  data () {    return {      isShow: false,//通過該屬性動態新增類,讓pdf顯示或隱藏      pdfDoc: null,//可以列印發現是一個物件,裡面有頁數資訊等      pageNum: 1,      pageRendering: false,      pageNumPending: null,      scale: 0.9    }  },  methods: {    closePdf(){      this.isShow = false    },    showPDF (url) {      this.isShow = true      let _this = this      PDFJS.getDocument(url).then(function (pdf) {        _this.pdfDoc = pdf        _this.renderPage(1)      })    },    renderPage (num) {      this.pageRendering = true      let _this = this      this.pdfDoc.getPage(num).then(function (page) {        var viewport = page.getViewport(_this.scale)        let canvas = document.getElementById('the-canvas')        canvas.height = viewport.height        canvas.width = viewport.width        // Render PDF page into canvas context        var renderContext = {          canvasContext: canvas.getContext('2d'),          viewport: viewport        }        var renderTask = page.render(renderContext)         // Wait for rendering to finish        renderTask.promise.then(function () {          _this.pageRendering = false          if (_this.pageNumPending !== null) {            // New page rendering is pending            this.renderPage(_this.pageNumPending)            _this.pageNumPending = null          }        })      })    },    queueRenderPage (num) {      if (this.pageRendering) {        this.pageNumPending = num      } else {        this.renderPage(num)      }    },    onPrevPage () {      if (this.pageNum <= 1) {        return      }      this.pageNum--      this.queueRenderPage(this.pageNum)    },    onNextPage () {      if (this.pageNum >= this.pdfDoc.numPages) {        return      }      this.pageNum++      this.queueRenderPage(this.pageNum)    }  }}</script><style scoped="" type="text/css">.back {  background-color: rgba(0, 0, 0, 0.788);  position:fixed;  width: 100%;  height: 100%;  top: 0;  left: 0;  text-align: center;  padding: 20px;  z-index: 100;  overflow: scroll;}.close{  position: absolute;  right: 20px;  top: 20px;  z-index: 200;  color: #fff;  cursor: pointer;} .foot {  position: absolute;  bottom: 50px;  left: 50%;  transform: translate(-50%,0);}</style>
複製程式碼

// index.jsimport PDF from './pdf' var $vmexport default {  install (Vue, options) {    if (!$vm) {      const PDFPlugin = Vue.extend(PDF)      $vm = new PDFPlugin().$mount()      document.body.appendChild($vm.$el)    }    Vue.prototype.$showPDF = function (url) {      $vm.showPDF(url)    }  }}複製程式碼

3. 在main.js中引入

import pdf from './components/pdf'
Vue.use(pdf)複製程式碼

這樣就可以全域性使用了,使用的時候就直接使用,本文是在一個圖片展示 的地方加上一個點選事件,點選時觸發該函式即可;

function showPdf(){
      let url = 'http://storage.xuetangx.com/public_assets/xuetangx/PDF/PlayerAPI_v1.0.6.pdf'        // let url = 'https://ecs7.tokopedia.net/instant-loan/file/29a2218e-bef9-44cb-b92b-8e81bc4d5228_DOC-20171013-WA0035.pdf'        this.$showPDF(url)}複製程式碼

文中新增了關閉功能,點選close即可關閉pdf的展示, 同時元件中也有分頁功能,如果頁數大於1就會顯示下一頁按鈕;

vue中如何實現pdf檔案預覽?

以上既是本人實現的過程,至於跨域問題,我這邊還沒遇到,現在是本地訪問可以的,等到線上再看看行不行,如果不行後邊再追加方法實現。

     

告訴親愛的自己,每天積累一點點,讓自己不斷的成長吧!!!!


相關文章