文章目录
- 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'
。
好彩一位博主的文章给了笔者思路。
- TypeError: Cannot read properties of undefined (reading ‘getReader’) #14850:啥用没有,题主提了相同的问题,下面的回复是让题主去参考官网的案例。。。💔
- 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. 前人的肩膀
- ng2-pdf-viewer(Github,有案例,有参数说明)
- Pdf.js body.getReader 报错问题
- ng2-pdf-viewer实践(欢迎阅读指正)
- JS中ArrayBuffer和Uint8Array区别
- Uint8Array
- ArrayBuffer
- FileReader