之前手里好几个项目都需要用到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>
其他框架同理,如有问题,欢迎评论!