pdf.js远程跨域访问+访问文件流

pdf.js远程跨域访问+访问文件流

前言:使用pdf.js之前首先得确定需要访问是的本项目PDF文件,还是远程PDF文件还是PDF文件,还是本地文件流,还是远程PDF文件流。我这里使用的是远程文件流的路径(具我目前的理解:文件流路径是可以直接访问下载的)。网上有很多教程,要么只是讲pdf.js跨域访问,要么就是pdf.js的文件流访问。所以会有有些人访问不到的情况。就因为我的是PDF文件流路径。这里就记录一下我遇到跨域访问文件流的过程。

  1. 下载pdf.js 官网。这里就不多介绍,网上很多有关结构目录的介绍。可以查看有关资料。
  2. 将下载的文件夹整个拷贝到项目中(我这里使用的是目前最新的pdfjs-2.5.207-dist)。这属于前端页面,只要拷贝到能访问页面的地方就可以了。如下图:
    在这里插入图片描述
  3. 这里需要处理两个问题:跨域和访问文件流

对于本项目中的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/article/details/93307643?utm_medium=distribute.pc_relevant.none-task-blog-baidulandingword-2&spm=1001.2101.3001.4242
  • https://blog.csdn.net/baby97/article/details/83410628
  • https://www.cnblogs.com/best-coder/p/11550409.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

£漫步 云端彡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值