之前手里好幾個項目都需要用到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'); // }
...
(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>
其他框架同理,如有問題,歡迎評論!