react-pdf在部分iOS手机上加载pdf失败问题解决

最近项目快结束了,测试提了一个bug,iOS手机上加载pdf一直在转圈,加载不出来内容。看到这个bug,在电脑上和安卓手机上没有问题,iOS手机中打开确实又问题,初步确定为app问题。我们的项目是集成在客户的app里的,可能是app内的WebView和Safari有一些差异导致的问题。

  1. 首先直接在iOS手机上用app和Safari分别访问本地启动的项目,发现打开之后一直转圈,但是没有报错信息,因为手机上是用vConsole看的,不确定是不是一些信息被过滤掉了,所以就在电脑上用Safari打开同一个页面,结果和手机上一样,依然没有报错信息。
  2. 因为没有错误信息,看了一会儿也没有头绪,突然想到之前遇到过,本地项目无法加载一些js,导致页面显示不全,有没有可能因为本地项目导致部分js加载不全,造成pdf加载不出来。尝试在电脑上用Safari打开远程页面,发现可以正常加载,手机上用Safari测试也可以正常加载,所以问题确定为iOS手机的app中无法加载pdf。
  3. app中无法加载,想到是不是pdf链接又问题,单独复制链接在代码中写死,测试发现也加载不出来。然后想到是不是app内部有网络限制,用app提供的方法ping pdf链接的域名,发现可以正常访问,所以排除链接和网络问题。
  4. 在github上react-pdf库的issues中搜索,发现有一个类似的问题,但是是Cordova的项目,情况应该不一样,所以就略过了。
  5. 没办法只能看react-pdf的源码,发现Document中除了之前用的onLoadSuccess方法,还有其他的onLoadErroronSourceSuccessonSourceError方法,加上这些方法,重新打包发布项目后,在app中打开发现,终于看到了一条有用的信息message: “undefined is not an object (evaluating ‘e.body.getReader’)”,再搜索源码,定位到报错位置是pdfjs中的PDFFetchStreamReader类中相关的方法报错,查看相关代码逻辑。传递pdf url后,pdfjs会请求这个url,拿到返回pdf数据后再去加载,现在是第一步请求pdf url没有返回数据导致报错,所以没有加载pdf。
  6. 搜索类似问题,发现Pdf.js body.getReader 报错问题,不过有点不同,这个问题是qq浏览器加载问题,不过提供了思路,需要手动请求pdf url,然后把数据内容赋值给pdfjs就可以正常加载了。
  7. 有思路之后,参考步骤4中的请求方法,在Document的onLoadError方法中,直接请求pdf url,把请求后的数据赋值给Document,这样就可以正常加载pdf了。
    onDocumentLoadError = (e) => {
      console.error('onDocumentLoadError', e);
      if (typeof this.state.pdfUrl == 'string') {
        this.transferUrlToArrBuffer(this.state.pdfUrl);
      }
    };
    transferUrlToArrBuffer = async (url) =>{
      const res = await fetch(url);
      const arrBuffer = await res.arrayBuffer();
      this.setState({pdfUrl: arrBuffer});
    };
    
  8. render中的方法如下,
    <Document
      file={pdfUrl}
      onLoadSuccess={this.onDocumentLoadSuccess}
      onLoadError={this.onDocumentLoadError}
      options={{
        cMapUrl: `//cdn.jsdelivr.net/npm/pdfjs-dist@${pdfjs.version}/cmaps/`,
        cMapPacked: true,
      }}
    >
      <Page pageNumber={1} onRenderSuccess={this.onLoadSuccess}/>
    </Document>
    
posted @ 2023-08-26 22:37  yuyuyu37  阅读(776)  评论(0编辑  收藏  举报