浅析前端预览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');
// }
然后重新加载发现可以完美的加载出来了。