vue-pdf.js 在线预览问题

JavaScript023

vue-pdf.js 在线预览问题,第1张

最近修改公司vue项目中使用pdf.js来实现在线预览上传的各类文件.由于使用pdf.js在预览时是直接在标签内将src属性赋值为要请求的地址.这就导致一个问题,会直接请求服务器的文件路径地址,而这个服务器文件路径就会暴露出来。处于安全性考虑在预览请求时不再返回地址,改为通过调用普通接口,而是统一返回流(word,pdf)或者base64(jpg,png...)。.前端再进行解析并实现在线预览.

此时遇到第一个问题:

        这个请求是在插件中进行的无法携带项目中封装的各类请求头信息(token..等)。 翻看pdf.js源码及网上总结.发现一个底层方法 

         该方法可传一个对象作为参数,对象内可以添加url(所请求的接口),headers(请求头信息)等.... . 有了这个方法就好处理了.

         最后在将该方法当做变量赋值给pdf的src.大功告成.

         最后再补充一些 : @loaded="docLoaded" @page-loaded ="pageLoaded" 这两个方法为加载预览文件时的loading事件,

最后引一波示例,

可参考:微信JS-SDK说明文档 >

此时可能出现白名单错误(忘截图了),需要在微信公众号中设置错误中的IP

注意:access_token和ticket都需要缓存

4. 获取签名 signature

将以上内容以键值对形式拼接,类似如下

本地引入sha1算法(需网上查找)

将上述拼接的字符串以参数的形式传递到sha1中得到 signature

signature = sha1(拼接完的字符串)

验证 signature 是否正确 >

将appId,nonceStr,timestamp和signature返回给前端

官网上是这样描述的:

这时候调用 updateAppMessageShareData , updateTimelineShareData 的时候就可以生效了,具体原理不清楚。。

注意:imgUrl配置有严格的要求

尺寸120 x 120,大小不超过10K,不支持GIF格式。必须采用https协议(最好写完整url),不支持base64。由于我使用的是vue,在webpack打包时图片小于10k的是会自动打包成base64导致无法正常显示图片,因此在webpack.base.config.js中修改默认配置

由于在网页中直接查看pdf的路径是无法在微信中查看(安卓)和分享(ios),因此使用pdf插件进行优化 --- pdf.js 。其原理是绘制成canvas,最终在真机上放大时可能出现模糊的问题。

创建之后控制台会报错出现跨域问题,因为pdf.js不支持跨域访问。此时可以将错误跨域信息在上一步你引入的文件中查找,然后将其判断语句注释掉即可解决这个问题。最后会发现pdf出现在这个容器中(忘截图了),也实现了微信中预览和分享的功能。

PDF.js 是基于开放的 HTML5 及 JavaScript 技术实现的开源产品。简单说就是一个 PDF 解析器。运用HTML5JavaScript(即pdf.js仅使用安全的web语言,不包含任何攻击者可以用的本地代码块)的PDF阅读器pdf.js,直接在标准的HTML页面上载入和渲染PDF文件, 还可以提高安全性(不需要安装第三方插件,安全性由浏览器保证),浏览器所做的安全措施已经为pdf.js提供了安全的运行环境。其对IE和 FireFox浏览器的要求是IE9+, FireFox19+。

在线示例: http://jsbin.com/pdfjs-helloworld-v2/1/edit , http://jsbin.com/pdfjs-prevnext-v2/1/edit

源码:https://github.com/mozilla/pdf.js

官网:http://mozilla.github.io/pdf.js/

pdf.js VS 传统浏览器读取pdf

一般来说,PDF档案格式都是在浏览器中由外挂程式来描绘,通常是Adobe自己的PDF reader或来自其他供应商的描绘工具,但这些外挂通常无法充分运用PDF的特点,而且由于含有大量的受信任代码,使得Google Chrome浏览器必须运用SandBox沙箱原理,来检查PDF描绘工具是否遭到未知病毒感染。

使用adobe,必须在本地安装软件才能使用,而pdf.js不依赖环境、渲染速度快(测试过,确实很快)、安全性高。

pdf.js渲染PDF文件

pdf.js渲染PDF文件的流程:Fetch pdf (url / buffer) ——>canvas ——>渲染

如果要深入pdf的渲染,需要去研究pdf.js源代码。pdf.js可通过pdf文件的地址或pdf数据流获取pdf,具体实现是调用接口函数 PDFJs.getDoc(url/buffer)将pdf载入html,通过canvas处理, 然后渲染pdf文件。网上给出的都是通过url来获取pdf的例子,而我在做项目的时候,后台(python)要求是发pdf的数据流给前台,前台接收pdf的buffer,然后通过pdf.js来渲染。当然最初尝试buffer出现了很多问题,具体问题总结如下:

1)如何通过$.ajax接收后台发给前台的buffer数据;

2)如何将buffer传给pdf.js来处理(这里我使用了viewer.js, 所以需要考虑的是如何将buffer传给viewer.js来处理);

3)如何将pdf.js转换成pdf.js可以接收的buffer格式;

(对应问题解决见代码注释)

注:viewer.js是pdf.js的扩展,其将打印、翻页、缩放等功能进行了实现,且界面非常好看。也就是说如果你引入了viewer.js,pdf的渲染和渲染之后的功能界面都已经帮你实现了,你不用自己去写界面。

先从官网:http://mozilla.github.io/pdf.js/ 下载代码,然后使用文件viewer.html , 我的html就是在viewer.html 的基础上修改的,下面我给出buffer的例子:

<!DOCTYPE html>

<html dir="ltr" mozdisallowselectionprint moznomarginboxes>

<head>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

<meta name="google" content="notranslate">

<title>在线预览</title>

{% load static %}{% get_static_prefix as STATIC_URL %}

<link href="{{STATIC_URL}}css/preview.css" rel="stylesheet" type="text/css" />

<link rel="stylesheet" href="{{STATIC_URL}}pdfjs/web/viewer.css"/>

<script type="text/javascript" src="{{STATIC_URL}}pdfjs/web/compatibility.js"></script>

<link rel="resource" type="application/l10n" href="{{STATIC_URL}}pdfjs/web/locale/locale.properties"/>

<script type="text/javascript" src="{{STATIC_URL}}pdfjs/web/l10n.js"></script>

<script type="text/javascript" src="{{STATIC_URL}}pdfjs/build/pdf.js"></script>

<script type="text/javascript" src="{{STATIC_URL}}pdfjs/web/debugger.js"></script>

<script src="{{STATIC_URL}}js/jquery-1.8.3.js" type="text/javascript"></script>

<script type="text/javascript">

//convertDataURIToBinary()

//不知道什么原因如果后台直接将pdf的数据流发给前台,得到的是乱码,将数据转换成 Uint8Array始终不成功

//所以就让后台将发送之前的数据流做 了base64编码发给前台,前台再解码得到的数据就不是乱码了。

var BASE64_MARKER = 'base64,'

var preFileId = {{mark}}

//viewer.js全局变量,传入buffer,回答问题2

var DEFAULT_URL

$(document).ready(function(){

$.ajax({

type:"post",

async: false,

//ajax接收pdf数据流,注意dataType值的设置是否有错,如果不指定,jQuery将自动根据HTTP包MIME信息返回

//responseXML或responseText . 回答问题1

contentType:"application/pdfcharset=utf-8",

url:"{% url netPan.File.views.browserFuf%}",

data:{

id: preFileId

},

success:function(data){

var pdfAsDataUri = data

//如果引入了viewer.js , 处理方法

var pdfAsArray = convertDataURIToBinary(pdfAsDataUri)

DEFAULT_URL = pdfAsArray

// 只引入了pdf.js, 未引入viewer.js, 处理方法

// var pdfAsArray = convertDataURIToBinary(pdfAsDataUri)

// PDFJS.getDocument(pdfAsArray).then()自己写pdf的处理函数

}

})

})

function convertDataURIToBinary(dataURI) { //编码转换,回答问题3

var base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length

var base64 = dataURI.substring(base64Index)

var raw = window.atob(base64)

var rawLength = raw.length

//转换成pdf.js能直接解析的Uint8Array类型,见pdf.js-4068

var array = new Uint8Array(new ArrayBuffer(rawLength))

for(i = 0i <rawLengthi++) {

array[i] = raw.charCodeAt(i)

}

return array

}

</script>

<!--先设置全局变量DEFAULT_URL 的值,所以要后调入viewer.js -->

<script type="text/javascript" src="{{STATIC_URL}}pdfjs/web/viewer.js"></script>

</head>

<body>

省略内容

</body>

</html>