赞
踩
我先说一下问题点:
最近项目做了一次改造,是关于iobs的。用户上传的pdf资料和图片等文件都是上传到iobs上,
所以用户需要预览或者页面返显图片的时候,都是从iobs上拿。之前拿到iobs链接之后,可以在一定的时间内无限次打开。这次做了安全改造,iobs链接只能用一次,再次打开的时候会报权限错误。这一改造就导致了页面预览pdf文件出现了问题。
安卓手机预览pdf文件,一切正常。
苹果手机预览pdf文件,小于1M可以预览,大于1M,显示一直加载中…
为什么苹果手机有问题,安卓手机没问题呢?
手机连接电脑进行调试后发现,因为pdf.js默认是分片加载,所以会发送多次请求,一个iobs链接会用多次。安卓手机第一次请求回来之后,后面第二次请求、第三次请求等都是从缓存(强缓存)中读取的,所以后面的请求不会到服务器,所以安卓名义上是只请求了一次。
但是苹果手机不是这样的,没有设置强缓存(苹果系统的安全机制是这样的,可以手动设置),所以分片加载会请求多次,第一次请求正常,后面的请求会出现请求报错的情况。
那又为什么小于1M的可以加载出来,大于1M的就不行呢?
因为小于1M的pdf资源请求会很快,所以在第二次请求、第三次请求等这些结果返回之前,第一次请求的结果已经返回来了,所以有数据,能正常加载。
大于1M的pdf资源请求会很慢,所以在第二次请求、第三次请求等这些结果返回之后,第一次请求的结果还没有返回回来,(第二次请求、第三次请求等请求响应的结果是权限错误,因为iobs链接已经用了不止一次),因为第二次请求、第三次请求等请求失败,所以第一次请求的响应结果也是请求报错(因为服务器认为)
因为pdf.js默认配置的是分片加载,分片加载的话,肯定会多次请求这个iobs链接的,现在iobs只能用一次,那就需要把pdf.js中分片加载的默认配置关掉;
我们先来看一下pdf.js的分片加载配置
PDF.js插件中切片配置相关属性如下:
##### 1 "disableAutoFetch": true, //是否禁用自动获取,true为禁用自动获取,开启分页
##### 2 "disableFontFace": false,
##### 3 "disableRange": false, //是否禁用range获取文件,false表示支持分页请求头
##### 4 "disableStream": true, //分页关键,是否禁用流的形式加载
既然知道了相关的配置属性,我就在pdf.js和viewer.js这两个js文件中进行了修改
viewer.js是在getDefaultPreferences这个函数中进行修改
function getDefaultPreferences(){
...
"disableAutoFetch": true,
// "disableAutoFetch": false, // 这个是默认的,所以需要改成true
"disableFontFace": false,
"disableRange": true,
// "disableRange": false,// 这个是默认的,所以需要改成true
"disableStream": true
// "disableStream": false // 这个是默认的,所以需要改成false
}
pdf.js是在getDocument这个函数中进行修改
function getDocument(){
...
if(typeof params.disableRange !== "boolean"){
// params.disableRange = false // 这个是默认的,所以需要改成true
params.disableRange = true
}
if(typeof params.disableStream !== "boolean"){
// params.disableStream = false // 这个是默认的,所以需要改成true
params.disableStream = true
}
if(typeof params.disableAutoFetch !== "boolean"){
// params.disableAutoFetch = false // 这个是默认的,所以需要改成true
params.disableAutoFetch = true
}
}
好,现在已经修改完默认的分片配置,改为不分片加载。
看看效果,配置成功,进入到预览pdf页面,只会iobs链接只会请求一次,说明分片加载已经关掉了。
如果仅仅是遇到上面这个问题,我就不写这篇总结了。
还遇到了这样一个问题,就是如果是1M以内的pdf数据,返回的响应头里面的content-type : application/octet-stream,可以被pdf.js正常加载预览。如果是大于1M的pdf数据,返回的响应头里面的content-type : application/pdf,这个时候被pdf.js加载预览时报 load failed(加载失败)。
为什么返回的响应头中的content-type 不一样呢,可能是iobs做了一些设置。不过通过查看iobs提供的接口文档,发现只要在url加上response-content-type这个值,就可以指定返回的响应头里面的content-type 值。
于是我就让后端小伙伴在url上加上了response-content-type这个值。加上后,生效了,大于1M的数据返回的响应头里面的content-type : application/octet-stream。
但是又出现新的问题,就是大于1M的数据无法被浏览器加载,这是为什么呢?
我又查看了一下配置,发现disableStream这个值我改为了true,是否禁用流的形式加载。这样的话,就相当于禁用流的形式进行加载了。
于是我把disableStream这个值我改回了false,最后的配置如下:
viewer.js是在getDefaultPreferences这个函数中进行修改
function getDefaultPreferences(){
...
"disableAutoFetch": true,
// "disableAutoFetch": false, // 这个是默认的,所以需要改成true
"disableFontFace": false,
"disableRange": true,
// "disableRange": false,// 这个是默认的,所以需要改成true
"disableStream": false
// "disableStream": false // 这个是默认的,所以需要改成false
}
pdf.js是在getDocument这个函数中进行修改
function getDocument(){
...
if(typeof params.disableRange !== "boolean"){
// params.disableRange = false // 这个是默认的,所以需要改成true
params.disableRange = true
}
if(typeof params.disableStream !== "boolean"){
// params.disableStream = false // 这个是默认的,所以需要改成true
params.disableStream = false
}
if(typeof params.disableAutoFetch !== "boolean"){
// params.disableAutoFetch = false // 这个是默认的,所以需要改成true
params.disableAutoFetch = true
}
}
好,现在已经修改完,大于1M的数据也可以被成功预览。
当然这其中有很多值得我去深挖的点。我后面会再写一篇,详细去介绍我深挖的哪些点,比如为什么1M以内的数据不受影响,大于1M的数据为什么会受影响。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。