pdf.js預覽base64格式的pdf(兼容ie10+)


之前手里好幾個項目都需要用到pdf預覽,在網上收羅了一大堆資料,最終選定了pdf.js。

原因:

  不用pdf.js的話,就需要去安裝各種環境的pdf插件,比如vue環境的vue-pdf,雖然可以自定義部分功能,但是除了它的展示,其他功能需要自己去添加(略麻煩),最不能忍的是不兼容ie!!!(看其他文章有適配ie的,不知道是不是博主環境版本原因,實在是顯示不了),對於angular環境,也沒找到適用的插件。

  pdf.js雖然只能兼容到ie10+,但現在都什么時代了,使用低版本瀏覽器的用戶畢竟占少數。而且它好歹是原生的,可以適用任何框架(jquery、vue及angular等),只要配置好一份插件,就可吃遍天下的既視感。

 

1.下載

參照鏈接:https://blog.csdn.net/houlai_houlai/article/details/86536316

博主用的鏈接文章中提到的第一種方法(使用自帶的viewer.html預覽)

插件存放路徑:原生框架可以放置任何位置,文中就放置於common/pdf路徑,vue與angular框架就需要放置於靜態資源文件static/pdf路徑

2.更改配置文件

參照鏈接:https://blog.csdn.net/xiao190128/article/details/100880675

(1)修改view.js(找到以下內容加以更改)

 // var DEFAULT_URL = 'compressed.tracemonkey-pldi-09.pdf'; '' //注釋默認
... //注釋對於是否允許跨域的判斷 // var viewerOrigin = new URL(window.location.href).origin || 'null'; // if (HOSTED_VIEWER_ORIGINS.indexOf(viewerOrigin) >= 0) { // return; // } // var fileOrigin = new URL(file, window.location.href).origin; // if (fileOrigin !== viewerOrigin) { // throw new Error('file origin does not match viewer\'s'); // }
  //當直接打開base64時,file是個對象,而不是string類型的url,所以此處需要判斷
  if (file && typeof file =='string') {
      var fileOrigin = new URL(file, window.location.href).origin;
  }
 
...
 
 webViewerOpenFileViaURL = function webViewerOpenFileViaURL(file) {
     //增加判斷file是string
    if (file && typeof file=='string' && file.lastIndexOf('file:', 0) === 0) {
      PDFViewerApplication.setTitleUsingUrl(file);
      var xhr = new XMLHttpRequest();
      xhr.onload = function () {
        PDFViewerApplication.open(new Uint8Array(xhr.response));
      };
      try {
        xhr.open('GET', file);
        xhr.responseType = 'arraybuffer';
        xhr.send();
      } catch (ex) {
        PDFViewerApplication.l10n.get('loading_error', null, 'An error occurred while loading the PDF.').then(function (msg) {
          PDFViewerApplication.error(msg, ex);
        });
      }
      return;
    }
    if (file) {
      PDFViewerApplication.open(file);
    }
  };

(2)修改view.html(下段代碼需放置於view.js文件引用之前)

上述鏈接的文中是用sessionStorage來存儲base64,會有一個弊端,如果base64太長,數據過大,會超出sessionStorage的存儲上限,這時候就會去想有沒有辦法擴大sessionStorage的存儲容量,博主找了一些方法,經測試之后都不能有效解決這個問題。最終選擇了一個穩妥的方式:用iframe嵌套(將數據存儲於iframe層某個dom元素里,獲取數據時直接在view.html層讀取父級dom元素的數據即可,就不用大費周章的去想怎么存儲數據的問題),在引用的時候會把具體代碼呈現。

<script type="text/javascript">
  var DEFAULT_URL = "";
  var pdfUrl = document.location.search.substring(1);
  if (null == pdfUrl || "" == pdfUrl) {
    var BASE64_MARKER = ';base64,'; //聲明文件流編碼格式
    var preFileId = "";
    var pdfAsDataUri = window.top.document.getElementById('baseUrl').innerHTML; //獲取父級dom存儲的數據 var pdfAsArray = convertDataURIToBinary(pdfAsDataUri);
    DEFAULT_URL = pdfAsArray;
    //編碼轉換
    function convertDataURIToBinary(dataURI) {
      //[RFC2045]中有規定:Base64一行不能超過76字符,超過則添加回車換行符。因此需要把base64字段中的換行符,回車符給去掉。
      var base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
      var newUrl = dataURI.substring(base64Index).replace(/[\n\r]/g, '');
      var raw = window.atob(newUrl); //這個方法在ie內核下無法正常解析。
      var rawLength = raw.length;
      //轉換成pdf.js能直接解析的Uint8Array類型
      var array = new Uint8Array(new ArrayBuffer(rawLength));
      for (i = 0; i < rawLength; i++) {
        array[i] = raw.charCodeAt(i) & 0xff;
      }
      return array;
    }
  }
</script>

3.引用(打開一個新窗口,以iframe的形式嵌套view.html)

文中數據來源是接口獲取,它可能是base64格式,也可能是文件流,博主下文都會給出具體示例。(接口需要的參數傳至下文提到的新頁面,接口也在該處調用,怎么打開新頁面並傳參就不用博主多講了。。)

(1)原生框架

新建pdf_view.html

html部分

<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv=Content-Type content="text/html; charset=utf-8">
    <title></title>
    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">
    <style>
      html,body, #content{height:100%;}
       body{margin:0;overflow:hidden;}
       #content{
         text-align:center;
         background:rgba(0,0,0,.6);
       }
       img{
         max-width:100%;
         max-height:100%;
       }
    </style>
</head>
<body>
<div id="baseUrl" hidden></div> <!--存儲base64數據-->
<div id="content"></div> <!--動態渲染iframe-->
</body>
</html>

script部分:

var common = require("common");
    var url = common.Url.resumeApiHost;
    var fileId = common.getQueryString('fileId');
    var fileName = common.getQueryString('fileName');
    document.title = fileName;  
    //獲取文件流
    function getFileBlob() {
      var header = {};
      header['Authorization'] = 'cmbnthr ' + common.Cookies.getCookie("userToken");
      new common.ajaxRequest({
          url: url  + "cmbntResume/attachment/view/"+fileId,
          type: "GET",
          param: '',
          header: header,
          callBack: function (data) {if(IEVersion()<10 && IEVersion()!=-1){
              common.Common.jAlert("請更新您的瀏覽器!");
              return;
            }
            $('#baseUrl').html('data:application/pdf;base64,'+data.data)
            $('#content').html('<iframe id="iframe" src="../../pdf/web/viewer.html" frameborder="0" width="100%" height="100%" border="0"></iframe>')
          }
      })
  }
  getFileBlob();
  //IE版本判斷
  function IEVersion() {
    var userAgent = navigator.userAgent; //取得瀏覽器的userAgent字符串
    var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1; //判斷是否IE<11瀏覽器
    var isEdge = userAgent.indexOf("Edge") > -1 && !isIE; //判斷是否IE的Edge瀏覽器
    var isIE11 = userAgent.indexOf('Trident') > -1 && userAgent.indexOf("rv:11.0") > -1;
    if (isIE) {
        var reIE = new RegExp("MSIE (\\d+\\.\\d+);");
        reIE.test(userAgent);
        var fIEVersion = parseFloat(RegExp["$1"]);
        if (fIEVersion == 7) {
            return 7;
        } else if (fIEVersion == 8) {
            return 8;
        } else if (fIEVersion == 9) {
            return 9;
        } else if (fIEVersion == 10) {
            return 10;
        } else {
            return 6;//IE版本<=7
        }
    } else if (isEdge) {
        return 'edge';//edge
    } else if (isIE11) {
        return 11; //IE11
    } else {
        return -1;//不是ie瀏覽器
    }
  }

(2)vue框架

新建pdfView.vue

<template>
  <div>
    <div id="baseUrl" hidden>{{pdfData}}</div>
    <iframe id="iframes" v-if="pdfData" :src="pdfUrl" frameborder="0" width="100%" height="100%"></iframe>
  </div>
</template>

<script>
  import { downloadFileBlob } from '@/api/checkAppointment/request'
  export default {
    data(){
      return{
        pdfUrl: '',
        pdfData: ''
      }
    },
    created(){
      downloadFileBlob({fileIDName: window.location.hash.split('=')[1] || ''}).then(res => {
    //這里返回的是文件流,把它轉換成base64格式
const blob = new Blob([res]) const _this = this var reader = new window.FileReader(); reader.readAsDataURL(blob); reader.onloadend = function() { _this.pdfData = reader.result; _this.pdfUrl="/static/pdf/web/viewer.html" } }) }, methods:{ } } </script> <style lang="scss" scoped> iframe{ height:calc(100vh - 20px) } </style>

其他框架同理,如有問題,歡迎評論!


免責聲明!

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



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