pdf.js远程跨域访问+访问文件流
日期: 2020-12-02 分类: 跨站数据测试 691次阅读
pdf.js远程跨域访问+访问文件流
前言:使用pdf.js之前首先得确定需要访问是的本项目PDF文件,还是远程PDF文件还是PDF文件,还是本地文件流,还是远程PDF文件流。我这里使用的是远程文件流的路径(具我目前的理解:文件流路径是可以直接访问下载的)。网上有很多教程,要么只是讲pdf.js跨域访问,要么就是pdf.js的文件流访问。所以会有有些人访问不到的情况。就因为我的是PDF文件流路径。这里就记录一下我遇到跨域访问文件流的过程。
- 下载pdf.js 官网。这里就不多介绍,网上很多有关结构目录的介绍。可以查看有关资料。
- 将下载的文件夹整个拷贝到项目中(我这里使用的是目前最新的pdfjs-2.5.207-dist)。这属于前端页面,只要拷贝到能访问页面的地方就可以了。如下图:
- 这里需要处理两个问题:跨域和访问文件流。
对于本项目中的PDF文件来说,访问很简单:如下代码:
<!-- ../js/pdfjs-2.5.207-dist/web/viewer.html是viewer.html的访问路径,file=后面是PDF文件路径。还有其他的访问方式,这里就不多介绍了,网上有很多 -->
<a href='../js/pdfjs-2.5.207-dist/web/viewer.html?file=PDF文件'>点击预览</a>
对于远程PDF文件的处理:首先需要修改两个文件的内容,viewer.html和viewer.js。
- 先说viewer.js文件,文件代码较多,建议使用搜索的方式:
找到以下代码:
function webViewerLoad() {
var config = getViewerConfiguration();
window.PDFViewerApplication = pdfjsWebApp.PDFViewerApplication;
window.PDFViewerApplicationOptions = pdfjsWebAppOptions.AppOptions;
var event = document.createEvent('CustomEvent');
event.initCustomEvent('webviewerloaded', true, true, {});
document.dispatchEvent(event);
pdfjsWebApp.PDFViewerApplication.run(config);
}
修改代码如下,可以将上面的代码注释掉,加入下面代码,我就是这样做的:
window.webViewerLoad=function webViewerLoad(fileUrl) {//调整了此行
var config = getViewerConfiguration();
window.PDFViewerApplication = pdfjsWebApp.PDFViewerApplication;
window.PDFViewerApplicationOptions = pdfjsWebAppOptions.AppOptions;
var event = document.createEvent('CustomEvent');
event.initCustomEvent('webviewerloaded', true, true, {});
document.dispatchEvent(event);
//调整了if 语句
if(fileUrl){
config.defaultUrl=fileUrl;
}
pdfjsWebApp.PDFViewerApplication.run(config);
}
- 注释掉以下代码,这段代码就在上面代码之下呢:
if (document.readyState === 'interactive' || document.readyState === 'complete') {
webViewerLoad();
} else {
document.addEventListener('DOMContentLoaded', webViewerLoad, true);
}
- 找到如下代码:
run: function run(config) {
this.initialize(config).then(webViewerInitialized);
}
//我的文件中不是这样的,是下面代码,两者是一样的
run(config) {
this.initialize(config).then(webViewerInitialized);
},
修改代码如下:
run: function run(config) {
//添加if语句
if(config.defaultUrl){
_app_options.AppOptions.set('defaultUrl',config.defaultUrl)
}
this.initialize(config).then(webViewerInitialized);
},
//我的修改是如下,其实一样
run(config) {
//添加if语句
if(config.defaultUrl){
_app_options.AppOptions.set('defaultUrl',config.defaultUrl)
}
this.initialize(config).then(webViewerInitialized);
},
- 接下来是viewer.html文件了,修改之前一定要引入jquery文件,因为这里需要用到ajax请求,解决跨域问题。以下加入的代码不需要更改,便可直接使用。
<!-- 在<script src="viewer.js"></script>之前引入以下代码,再次强调,需要引入jquery -->
<script type="text/javascript">
$(()=>{
//获取要跨域访问的pdf地址
var url = getUrlParam("urlPath");
console.log(url)
xhrPdf(url,function(href){
//调用viewer.js方法预览pdf
webViewerLoad(href)
})
})
//获取url中的参数
function getUrlParam(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象
var r = window.location.search.substr(1).match(reg); //匹配目标参数
if (r != null) return unescape(r[2]); return null; //返回参数值
}
//添加xhrPdf函数
function xhrPdf(urlPath,callback) {
$.ajax({
type: "post",
async: false,
mimeType: 'text/plain; charset=x-user-defined',
url: "/WechatApp/manual/pdfStreamHandler", //请求服务器数据 获取pdf数据流,
data:{
urlPath:urlPath
},
success: function(data) {
var rawLength = data.length;
//转换成pdf.js能直接解析的Uint8Array类型,见pdf.js-4068
var array = new Uint8Array(new ArrayBuffer(rawLength));
for (var i = 0;i < rawLength; i++) {
array[i] = data.charCodeAt(i) & 0xff;
}
var href = window.URL.createObjectURL(new Blob([array]));//数据流转换成createObjectURL能解析的Blob类型
callback(href) //返回url
}
});
}
</script>
- 这里并没有真正解决跨域问题,通过间接转换的方式解决的。主要是通过调用后端mapping,将PDF文件转为PDF文件流来操作的,这个网上教程到处都是。但是如果已经知道的路径就是PDF文件流了怎么办?这里就需要在后端controller中创建一个请求,作相应的处理,然后把流数据传到前端,这样前端就可以访问了PDF文件了。
我这里处理如下:创建如下mapping
@RequestMapping(value = "/pdfStreamHandler")
public void getRemoteFile(String urlPath, HttpServletResponse response) {
InputStream inputStream = null;
try {
try {
String strUrl = urlPath.trim();
URL url = new URL(strUrl);
//打开请求连接
URLConnection connection = url.openConnection();
HttpURLConnection httpURLConnection = (HttpURLConnection) connection;
httpURLConnection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
// 取得输入流,并使用Reader读取
inputStream = httpURLConnection.getInputStream();
/**
* 以上的操作处理是处理文件流的,如果访问的是远程PDF文件
* 可以直接new File("文件路径"),然后传给inputStream,
* 然后以下操作不变。
*/
int bytesum = 0;
int byteread = 0;
byte[] buffer = new byte[1024];
// 清空response
response.reset();
// 设置response的Header
response.addHeader("Content-Disposition", "attachment;filename=" + new String("cbzm.pdf".getBytes()));
OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/octet-stream");
bytesum = 0;
byteread = 0;
buffer = new byte[1024];
while ((byteread = inputStream.read(buffer)) != -1) {
bytesum += byteread;
toClient.write(buffer, 0, byteread);
}
toClient.flush();
inputStream.close();
toClient.close();
} catch (IOException e) {
e.printStackTrace();
inputStream = null;
}
} catch (Exception e) {
e.printStackTrace();
inputStream = null;
}
}
- 调用方法如下:
<!-- 其实和上面的调用没什么区别,知识把file换成了urlPath,如果需要自定义参数名的话,可以修改viewer.html中getUrlParam("urlPath")这个方法的参数,起成自己喜欢的名字 -->
<!-- 因为viewer.html的调用方法很多,我就这这样子举例,如果说想研究的话,可以尝试其他方法是否可以调用 -->
<a href='../js/pdfjs-2.5.207-dist/web/viewer.html?urlPath=PDF路径即可'>点击预览</a>
- 参考文章:
- https://blog.csdn.net/wf001015
除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog
上一篇: 以AI优势激发数据潜能,这场TechDay干货满满
下一篇: 阿里云性能测试工具PTS
精华推荐