使用pdf.js预览pdf遇到的问题总结

105 篇文章 2 订阅
100 篇文章 6 订阅

我先说一下问题点:

最近项目做了一次改造,是关于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是默认的,之前改为true了,所以需要再改为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 // false是默认的,之前改为true了,所以需要再改为false
      params.disableStream = false
   }
   if(typeof params.disableAutoFetch !== "boolean"){
      // params.disableAutoFetch = false // 这个是默认的,所以需要改成true
      params.disableAutoFetch = true
   }
}

好,现在已经修改完,大于1M的数据也可以被成功预览。

当然这其中有很多值得我去深挖的点。我后面会再写一篇,详细去介绍我深挖的哪些点,比如为什么1M以内的数据不受影响,大于1M的数据为什么会受影响。

  • 17
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值