基于pdf.js简单在线pdf文件预览跨域解决方案,兼容性好!
主要内容
基于pdf.js的移动端在线pdf文件预览,支持跨域的源码,兼容性强,不受浏览器约束,还可以将pdf转成图片。
了解跨域
-
什么是跨域?
跨域是指从一个域名去请求另一个域名的资源,严格来说,只要域名,协议,端口任何一个不同,就视为跨域。 -
为什么会出现跨域?
为了网络安全起见,浏览器设置了一个同源策略,规定只有域名,端口,协议全部相同,就叫做同源。当页面在执行一个脚本时,会检查访问的资源是否同源,如果不是,就会报错。可是在实际开发中,经常会有跨域加载资源的需求,避免不了跨域请求,所以就出现了跨域。 -
什么是同源策略及限制?
同源策略是指从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互,这是一个用来隔离潜在恶意文件的的关键的安全机制。不同源之间的交互是被浏览器限制的,为了安全起见。 -
常用的跨域方法是什么?
1、JSONP – 原理就是利用了script标签,在标签外套了一层壳,利用标签特性达到跨域加载资源的效果。
JSONP由两部分组成,回调函数和数据
优点:
(1)兼容性好,在多古老的浏览器都能运行。
(2)能直接访问响应文本,支持在浏览器与服务器之间双向通信。
缺点:
(1)只支持GET请求,不支持POST请求;
(2)不够安全。因为JSONP是从其他域中加载代码执行,如果其他域不安全,可能会在响应中带有恶意代码。
(3)不容易确认请求是否失败。
2、CORS – 跨站资源共享,它是跨域的官方解决方案,升级版的JSONP。原理是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。请求和响应都不包含cookie信息。
CORS需要浏览器和后院同时支持,浏览器会自动进行CORS通信,实现CORS通信的关键是后端,只要后端实现了CORS,就实现了跨域,服务端设置Access-Control-Allow-Origin 就可以开启CORS,该属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源。
3、webSockets – 不受同源策略影响。原理是因为它不使用HTTP协议,而使用一种自定义的协议,专门为快速传输小数据设计。
4、Nginx – 代理跨域。反向代理跨域。
前提条件
- 必须拥有两个域的支配权,这个非常重要!(之所以存在跨域这个问题,我查了查,感觉主要也是为了网络的安全JS脚本的同源策略及限制,毕竟现实中也有划分界限的说法,但是同样也有牛逼的人可以占有两个领域的,所以就要解决跨域了);
- 本文是建立在PHP的基础上的,但是其他语言同样可行;
- 本文采用CORS – 跨站资源共享解决方案。
具体实现
1.引入pdf.js
例如:
<script src="pdf.js" type="text/javascript"></script>
<script src="pdf.worker.js" type="text/javascript"></script>
2.获取pdf文件总页数
例如:
PDFJS.getDocument(url).then(function getPdfHelloWorld(pdf) {
pages = pdf.numPages;//获取总页数
for(var i = 1;i < pdf.numPages;i++){//循环输出
}
});
3.获取每页的内容
例如(具体1参数详见官方API):
function showall(url,page,id){
PDFJS.getDocument(url).then(function getPdfHelloWorld(pdf) {
pdf.getPage(page).then(function getPageHelloWorld(page) {
var scale = 1.0;
var viewport = page.getViewport(scale);
var canvas = document.getElementById(id);
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
var renderContext = {
canvasContext: context,
viewport: viewport
};
page.render(renderContext);
});
});
}
4.跨域问题(重要)
对于pdf.js单方面想要解决跨域问题只能说能力有限,想要解决还要从服务器端下手,通过修改http报头为header(‘Access-Control-Allow-Origin:*’),为什么这样可以自行百度。
PHP服务端配置test.php
function sendfile( $fullPath ){
$fsize = filesize($fullPath);
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: application/pdf");
header('Access-Control-Allow-Origin:*');
header("Content-Disposition: attachment; filename=\"".basename($fullPath)."\";" );
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".$fsize);
ob_clean();
flush();
readfile( $fullPath );
}
客户端配置
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
.lightbox {
position: fixed;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
z-index: 7;
opacity: 0.3;
display: block;
background-color: rgb(0, 0, 0);
}
.close {
position: relative;
z-index: 10;
text-align: center;
color: red;
font-size: 18px;
}
.pop {
position: relative;
text-align: center;
z-index: 9;
}
.pop canvas {
margin: 20px auto;
display: block;
}
</style>
</head>
<body>
<h1><a href="javascript:void(0)" target="_blank" onclick="showPdf()">显示pdf文档</a></h1>
<h1><a href="http://XXXXXXXXXXX/test.php">下载pdf文档</a></h1>
<div id="container" style="display: none;">
<div class="lightbox"></div>
<div id="close" class="close">关闭</div>
<div id="pop" class="pop"></div>
</div>
</body>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script src="pdf.js" type="text/javascript"></script>
<script src="pdf.worker.js" type="text/javascript"></script>
<script type="text/javascript">
function showall(url, page, id) {
PDFJS.getDocument(url).then(function getPdfHelloWorld(pdf) {
console.log(pdf.numPages);
pdf.getPage(page).then(function getPageHelloWorld(page) {
var scale = 1.0;
var viewport = page.getViewport(scale);
var canvas = document.getElementById(id);
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
var renderContext = {
canvasContext: context,
viewport: viewport
};
page.render(renderContext);
});
});
}
function showPdf() {
var url = 'http://XXXXXXXXXXX/test.php';//pdf文件地址
$("#container").show();
$("#pop").empty();
PDFJS.getDocument(url).then(function getPdfHelloWorld(pdf) {
pages = pdf.numPages;
for(var i = 1; i < pdf.numPages; i++) {
var id = 'page-id-' + i;
$("#pop").append('<canvas id="' + id + '"></canvas>');
showall(url, i, id);
}
});
}
$("#close").click(function() {
$("#container").hide();
});
</script>
</html>
5.效果预览