首页 前端知识 PDF预览异常:Cannot read properties of undefined (reading ‘getReader‘)

PDF预览异常:Cannot read properties of undefined (reading ‘getReader‘)

2024-05-13 10:05:44 前端知识 前端哥 660 513 我要收藏

文章目录

    • 1. 异常描述
    • 2. 问题排查
      • 2.1 版本冲突?
      • 2.2 使用方式
    • 3. ng2-pdf-viewer的使用
    • 4. 解决方案
    • 5. 前人的肩膀

1. 异常描述

​ 这周线上环境报了一个异常,用户在移动端预览文件时报错,错误信息:“UnknownErrorException: Cannot read properties of undefined (reading ‘getReader’)”

在这里插入图片描述

2. 问题排查

2.1 版本冲突?

​ 笔者也很纳闷,最近没有改过代码,没有改过依赖,虽然有上线但都是改容器的配置。但上线就会重新部署,于是笔者怀疑是重新拉取底层依赖的时候依赖版本发生了变化。(笔者也不确定。。不李姐。。)

​ 于是在本地运行了项目,可以正常预览,但是测试环境同线上报同样的错误(“在我电脑运行的好好的”)。没办法基于上面的猜想只能先改下依赖,于是使用之前在另一个项目实践的可行版本组合修改依赖版本。(笔者之前在另一个项目中负责预览功能,自己写了一个简单pdf预览,遇到了版本不匹配的问题,修复后总结为文章 ng2-pdf-viewer实践,欢迎阅读指正)

​ 根据之前的实践,笔者修改了package.json、package-lock.json,然后发布测试环境测试,但依然没能解决这个问题,报同样的错误。

2.2 使用方式

​ 莫得办法,上网搜索,但搜索结果却寥寥无几。好多回复说是因为对象为undefined然后去调用了其方法,好吧,谜底就在谜面上。。或者是什么 reading 'catch'reading 'xxx'

​ 好彩一位博主的文章给了笔者思路。

  1. TypeError: Cannot read properties of undefined (reading ‘getReader’) #14850:啥用没有,题主提了相同的问题,下面的回复是让题主去参考官网的案例。。。💔
  2. Pdf.js body.getReader 报错问题:博主描述了相同的问题,根据源码的指引,确定了报错的具体位置,并提出了解决方案。虽然博主的使用方式同笔者不同,但根据该文章,笔直更改了ng2-pdf-viewer的入参方式,解决这个问题,即将入参改为Uint8Array数据。

3. ng2-pdf-viewer的使用

​ 在报错的项目中,ng2-pdf-viewer的使用方式如下:

<pdf-viewer [src]="pdfUrl"
            [render-text]="true"
            style="display: block; height: 500px;"
></pdf-viewer>

​ src的入参是一个url链接,pdf-viewer组件拿到url链接后会发送一个网络请求,取回blob数据进行展示,在对响应体进行处理的过程中报错。这就是令人困惑的地方,这个url返回的是blob格式的数据,源码为什么要调用response.body.getReader(),response就是blob,还要去获取body?

​ 那么来看下src参数,进入pdf-viewer源码:

src: string | Uint8Array | PDFSource;

​ 于是笔直将src的参数从url链接改为Uint8Array数据,笔直在 ng2-pdf-viewer实践 中使用的就是这种方式,因为没有去做网络请求,而是直接读取了一个本地文件,然后将本地文件转为ArrayBuffer传给src参数。

(Uint8Array 和 ArrayBuffer的区别和联系可自行查阅资料,或者参考 JS中ArrayBuffer和Uint8Array区别)

4. 解决方案

​ OK,那么对代码进行改造。

html

<pdf-viewer [src]="pdfSrc"
            [render-text]="true"
            style="display: block; height: 500px;"
            onError="pdfError($event)"
></pdf-viewer>

component

ngOnInit() {
  // 网络请求,获取blob数据
  const blob = await this.attachService.getPdf(this.pdfUrl).toPromise();
  const reader = new FileReader();
  reader.readAsArrayBuffer(blob);
  // 注意,reader.result不能直接访问,需要调用.onload,加载后在回调函数中获取
  // 笔者一开始也是将reader定为全局变量,然后将reader.result直接赋值给[src]发现不起作用!!!
  // 才回去看FileReader文档的
  reader.onload = () => {
    this.pdfSrc = reader.result;
  }
}

// 之前在做预览功能的时候看到用网友提问说预览空白,其实可以使用onError将异常输出用于排查问题
pdfError($event){
  console.log($event);
  // 友好提示
}

​ 好了,只能说问题解决了,pdf可以正常预览,但底层的具体原因,笔者也不知道,欢迎补充。一个是在代码、package.json没有改动的情况下为什么不可预览了,原先功能是OK的;二是,入参是url,为何要调用.body.getReader()。不李姐,持续学习吧。

5. 前人的肩膀

  1. ng2-pdf-viewer(Github,有案例,有参数说明)
  2. Pdf.js body.getReader 报错问题
  3. ng2-pdf-viewer实践(欢迎阅读指正)
  4. JS中ArrayBuffer和Uint8Array区别
  5. Uint8Array
  6. ArrayBuffer
  7. FileReader
转载请注明出处或者链接地址:https://www.qianduange.cn//article/8494.html
标签
评论
会员中心 联系我 留言建议 回顶部
复制成功!