vue 中展示PDF內容


vue 中展示PDF內容

不久前有個需要改的需求,以前是直接根據鏈接讓用戶下載對應pdf文件來查看,最主要是給用戶查看,然而這種並不是很安全的,其他用戶可以進行下載或者使用pdf鏈接分享給其他人,所以后來需要驗證后再進行展示pdf內容,只有對應知道的人自己驗證后才能打開;

這里說下自己的實現吧,讀取pdf,那么在純靜態的使用vue-cli搭建的網站中讀取pdf文件是不行的,何況涉及到驗證,那么只有調用接口來處理,但是讀取pdf文件展示就需要組件,找了pdf.js 來使用,根據官方文檔,pdf文件不能夠使用其他網站的,也就是不能跨域,不過幸好可以加載文件流進去,至此 驗證=>獲取文件流數據=>渲染 完成,下方給的是處理代碼

loadFile(data) {
    let _this = this;
    let transData = window.atob(data);
    PDFJS.getDocument({ data: transData }).then(pdf => {
        _this.pdfDoc = pdf;
        _this.pages = _this.pdfDoc.numPages;
        _this.$nextTick(() => {
            _this.renderPage(1);
        });
    });
}
renderPage(num) {
   let _this = this;
   this.pdfDoc.getPage(num).then(page => {
       let canvas = document.getElementById("the-canvas" + num);
       let ctx = canvas.getContext("2d");
       let dpr = window.devicePixelRatio || 1;
       let bsr =
           ctx.webkitBackingStorePixelRatio ||
           ctx.mozBackingStorePixelRatio ||
           ctx.msBackingStorePixelRatio ||
           ctx.oBackingStorePixelRatio ||
           ctx.backingStorePixelRatio ||
           1;
       let ratio = dpr / bsr;
       let viewport = page.getViewport(
           screen.availWidth / page.getViewport(1).width
       );
       canvas.width = viewport.width * ratio;
       canvas.height = viewport.height * ratio;
       canvas.style.width = viewport.width + "px";
       canvas.style.height = viewport.height + "px";
       ctx.setTransform(ratio, 0, 0, ratio, 0, 0);
       ctx.fillStyle = "#fff";
       ctx.fillRect(0, 0, canvas.width, canvas.height);
       let renderContext = {
           canvasContext: ctx,
           viewport: viewport
       };
       page.render(renderContext).promise.then(()=>{
           //這一段處理涉及到展示處理
           _this.transImg(
               canvas,
               canvas.style.width,
               canvas.style.height,
               num
           );
       });
       if (_this.pages > num) {
           _this.renderPage(num + 1);
       }
   });
}
//這一段處理涉及到展示處理
transImg(canvas, w, h, num) {
    var image = new Image();
    image.src = canvas.toDataURL("image/jpeg");
    image.className = "trans-img";
    image.setAttribute("preview", 1);
    $("#pdf-img").append(image);
    let _self = this;
    if (this.pages <= num) {
        setTimeout(() => {
            _self.loadingConfig.isShow = false;
            _self.$previewRefresh();
        }, 500);
    }
}

用到的 window.atob()

關於這一段處理涉及到展示的注釋,因為用戶要查看以canvas承載的pdf文字,但是查看體驗並不是很好,文字很小,也不能放大,那么就需要處理這塊問題,找了幾個插件,試了vue-photo-preview 這個組件滿足條件,不過由於它是使用的img,所以我上邊處理給成了img並隱藏對應canvas展示,根據vue-photo-preview 所定的規范來處理,效果還是不錯的,不過pdf.js這個組件比較大,我采用了cdn引用了js,以下是剩余部分:

<template>
  <div class="pdf-body">
    <canvas v-for="page in pages" :id="'the-canvas'+page" :key="page" style="display:none;"></canvas>
    <div id="pdf-img"></div>
    <loading :show="loadingConfig.isShow" :text="loadingConfig.text"></loading>
  </div>
</template>

至此,優化差不多了
補充一下,在canvas寫入時有問題,那么需要改一下順序了

page.render(renderContext).promise.then(()=>{
           //這一段處理涉及到展示處理
           _this.transImg(
               canvas,
               canvas.style.width,
               canvas.style.height,
               num
           );
});
 if (_this.pages > num) {
     _this.renderPage(num + 1);
}
//上方這一段需要替換成下方這一段,添加一個data:canvasList  
        page.render(renderContext).promise.then(() => {
          _this.canvasList.push({
            index: num,
            canvasData: canvas
          });
          if (_this.pages > num) {
            _this.renderPage(num + 1);
          } else {
            _this.canvasList = _this.canvasList.sort((a, b) => {
              return a.index - b.index;
            })
            _this.canvasList.forEach(item => {
              _this.transImg(item.canvasData,canvasData.style.width, canvasData.style.height, item.index);
            });
          }
        });


免責聲明!

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



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