最近在ionic项目中,用ng2-pdf-viewer开发PDF浏览功能时遇到一个问题,表现就是插件一直白屏,PDF文件的内容不显示,如果给<pdf-viewer>加上错误事件监听:
<pdf-viewer [src]="pdfSrc" (error)="onError($event)">
onError(error: any) { console.log('PDF error', error); }
在控制台可以看到报错 Setting up fake worker fail. cannot load script https://cdnjs.cloudflare.com/...
在node_modules/ng2-pdf-viewer/fesm2015/ng2-pdf-viewer.js中可以找到以下代码:
let pdfWorkerSrc; if (window.hasOwnProperty('pdfWorkerSrc') && typeof window.pdfWorkerSrc === 'string' && window.pdfWorkerSrc) { pdfWorkerSrc = window.pdfWorkerSrc; } else { pdfWorkerSrc = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${PDFJS.version}/pdf.worker.min.js`; } PDFJS.GlobalWorkerOptions.workerSrc = pdfWorkerSrc;
意思就是说,当window.pdfWorkerSrc有值时就用window.pdfWorkerSrc,否则就去指定的CDN加载pdf.worker.min.js。
解决方法:
第一步,在自己的组件或页面代码中加入以下代码:
ngOnInit() { //... (<any>window).pdfWorkerSrc = 'assets/js/pdf.worker.min.js'; }
第二步,在项目根目录下的angular.json中如下位置中增加下面红色的代码。
{ ... "projects": { "app": { "architect": { "build": { ... "options": { ... "assets": [ ... { "glob": "pdf.worker.min.js", "input": "node_modules/pdfjs-dist/build/", "output": "/assets/js/" } ], ...
加这段代码的意思就是在构建时将 node_modules/pdfjs-dist/build/pdf.worker.min.js复制到www/assets/js/下,(注www是ionic的默认输出目录,见angular.json中的outputPath)。另外,ionic serve时是将输出文件放在内存中提供的服务,所以在文件系统中并看不到。如果你执行ionic build 就可以在生成www目录,并在其下找到对应的文件了。
之前在网上看到别的解决方案是直接把pdf.worker.min.js文件复制到assets/js/下,但这样有缺点,就是如果ng2-pdf-viewer升级了,那自己复制的pdf.worker.min.js文件的版本可能就跟ng2-pdf-viewer需要的版本不一致了,还需要手动维护更新。
总结:
官方文档关于worker相关说明https://github.com/VadimDez/ng2-pdf-viewer/blob/master/README.md#set-custom-path-to-the-worker,翻译如下:
------------------------------------------------------------
默认情况下worker是从cdnjs.cloudflare.com加载,可以设为自己的路径,比如,在你的代码中更新worker的路径为/pdf.worker.js:
(window as any).pdfWorkerSrc = '/pdf.worker.js';
此代码应该加在pdf-viewer组件被渲染之前。(注意,/pdf.worker.js,这个路径要改成自己的实际路径)。
--------------------------------------------------------------
这个问题只在没有外网的情况下才会发现,因为ng2-pdf-viewer需要去cdn上加载这个pdf.worker.min.js,至于为什么没有直接引用pdfjs-dist/build/pdf.worker.min.js,原作者说是因为pdfjs-dist/build/pdf.worker.min.js会引起webpack错误。所以才在运行时动态加载。而我们在无外网环境下开发就会加载不上pdf.worker.min.js,然后就出现了PDF内容不能正常显示的问题。