浅析前端预览PDF文件方案及解决PDF.js访问远程服务器报file origin does not match viewer's的问题

一、解决方案

1、方案一:使用 iframe、embed、新窗口打开。使用方式如下:

<embed src="test.pdf">
<iframe src="test.pdf"></iframe>

  优点:简单,支持大部分 PC 浏览器,跨域资源同样可以(无需 cors)

  缺点:不支持移动端浏览器,不支持 IE 等低版本浏览器。样式无法自定义

2、方案二:pdfjs-view

  方案兼容性比较好,需要资源同域 或者 cors跨域,可以自定义样式。

(1)可以使用使用 CDN 或者官方提供的 pdfjs-view。(不推荐,不稳定,异常CORS)

https://mozilla.github.io/pdf.js/legacy/web/viewer.html

https://mozilla.github.io/pdf.js/web/viewer.html

(2)下载 pdf.js 源码,然后自己部署 pdfjs-view。可以放工程中,也可以放服务器中

  优点:如果需要改什么东西,需要自定义样式什么的,可以直接修改 viewer.html 即可,使用方便,且完全跟浏览器预览pdf是一样的

3、方案三:pdfjs-canvas

  方案比较复杂,需要自己实现一套预览配套的内容(分页、放大缩小)

二、使用pdfjs实现PDF的预览

  核心部分是pdf.js和pdf.worker.js,一个负责API解析,一个负责核心解析。

  实现pdf预览主要有两种方式:

1、第一种方式:使用viewer.html 以读取文件流方式在线展示pdf文件

  使用pdfjs已经写好的viewer.html页面。可以将pdfjs代码放在工程里,也可以放到服务器上,因为放到本地包有点大。

2、第二种方式:将PDF文件渲染成Canvas

// 1、安装
npm i pdfjs-dist

// 2、引入pdf.js
import PDFJS from 'pdfjs-dist'
const worderSrc = require('pdfjs-dist/build/pdf.worker.min.js')

// 3、html部分
<div class="pdf-container">
    <canvas v-for="index in totalPage" :key="index" :id="`canvas-${index}`"></canvas>
</div>

// 4、核心代码
    PDFJS.GlobalWorkerOptions.workerSrc = worderSrc
    // this.pdfPath pdf地址,如果是流需单独处理一下
    PDFJS.getDocument(this.pdfPath).promise.then(pdfDocument => {
      this.totalPage = pdfDocument.numPages // 页码
      for (let i = 1; i <= pdfDocument.numPages; i++) {
        pdfDocument.getPage(i).then(pdfPage => {
          let viewport = pdfPage.getViewport(2.0)
          let canvas = document.getElementById(`canvas-${i}`)
          canvas.width = viewport.width
          canvas.height = viewport.height
          let ctx = canvas.getContext('2d')
          let renderTask = pdfPage.render({
            canvasContext: ctx,
            viewport: viewport
          })
          return renderTask.promise
        })
      }
    }).catch(reason => console.error('PDF加载失败'))

三、PDF.js访问远程服务器报file origin does not match viewer's

  下载PDF.js,其中包含两个文件夹build和web文件夹,build文件夹是PDF.js核心文件,web下为展示PDF的视图界面viewer.html;

  在项目中要在线预览PDF,进行以下步骤:

1、方法1:

  新建一个html页面,在页面中使用iframe标签,通过iframe标签嵌套viewer.html,如果是只加载本地文件,在viewer.js修改默认的pdf文件路径(DEFAULT_URL字段)即可。

<iframe src="web/viewer.html" width="100%" height="800px" id="Iframe"></iframe>
// 修改viewer.js的默认的pdf的文件路径
// var DEFAULT_URL = 'test.pdf';

2、方法2:

  但是我们的需求往往不是加载一张静止的PDF文件,所以我们通常用的比较多的是第二种方法加载远程服务器返回pdf文件流,然后在viewer.html的url后面添加file=http://127.0.0.1:8088/PDF/test.pdf;我是这样使用的:

<iframe :class="{'iframe1000' : isFullscreen}"
  frameborder="0"
  height="100%"
  :src="`/pdfjs/web/viewer.html?file=${detail.url}`">
</iframe>

  这样就实现了预览远程服务器的文件流,但是pdf.js不支持跨域请求,所以会报错:file origin does not match viewer’s,试了很多种方法仍然报错,所以简单粗暴的方法就是把viewer.js的判断远程地址的代码注释掉即可。

// 需要在viewer.js中注释的代码如下:
// if (origin !== viewerOrigin && protocol !== 'blob:') {
//   throw new Error('file origin does not match viewer\'s');
// }

  然后重新加载发现可以完美的加载出来了。

posted @ 2018-06-20 22:21  古兰精  阅读(4350)  评论(0编辑  收藏  举报