ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

vue组件vue-pdf遇到的啃加载pdf替换的内容不显示的问题

2021-09-18 14:58:25  阅读:398  来源: 互联网

标签:bcmap vue js PDF pdf 加载


最近做移动端项目,封装PDF预览组件,同事开始用的是vue-pdf来做的预览,连连踩坑,基本遇到3个问题:
1、PDF中文不显示
2、PDF签章没显示出来,控制台提示:Warning: Unimplemented widget field type "Sig", falling back to base field type
3、第二次打开PDF的时候会遇到PDF空白的问题,控制台提示:Error during font loading: Failed to execute 'postMessage' on 'Worker': ArrayBuffer at index 0 is already detached

对于问题1,大家的做法都一样,通过引入CMapReaderFactory.js解决问题:

import CMapReaderFactory from 'vue-pdf/src/CMapReaderFactory.js'

    this.src = pdf.createLoadingTask({
      url: this.pdfUrl,
      CMapReaderFactory
    });

引入CMapReaderFactory.js确实解决了问题1,但是这也会引起问题3的出现,这个我们聊完问题二再说。

对于问题二,网上也有很多解决办法,vue-pdf实际上也是集成了pdfJS的实现,一般通过注释pdfJS中的代码,开启签章即可解决问题,参考http://www.zyiz.net/tech/detail-129606.html:

//pdf.worker.js

if (data.fieldType === 'Sig') {

  data.fieldValue = null;

    //注释此行代码即可

  //_this3.setFlags(_util.AnnotationFlag.HIDDEN);

}

对于问题三,前面提到是由于 引入了CMapReaderFactory导致的,你代码断点进去就会发现他的代码是这样写的:

import { CMapCompressionType } from 'pdfjs-dist/build/pdf.js'

// see https://github.com/mozilla/pdf.js/blob/628e70fbb5dea3b9066aa5c34cca70aaafef8db2/src/display/dom_utils.js#L64

export default function() {    this.fetch = async function(query) {
        
        /* webpackChunkName: "noprefetch-[request]" */
        return import('./buffer-loader!pdfjs-dist/cmaps/'+query.name+'.bcmap')
        .then(function(bcmap) {

            return {
                cMapData: bcmap.default,
                compressionType: CMapCompressionType.BINARY,
            };
        });
    }
};

这段代码通过动态import PDF的语言文件实现解决中文显示的问题,但是第二次加载PDF的时候你会发现加载的页面是空白页,我调试了一天,才发现这坑爹玩意在你第一次加载PDF的时候,bcmap的返回值是Uint8Array[43366]的数组对象,而第二次预览PDF加载时发现bcmap的返回值是Uint8Array []的空数组,断点进去看了一下也没看的明了,但是大概能猜到是因为缓存问题,第二次加载时取的是初次加载PDF文件时的语言文件的loadModules的缓存,但是取的过程中导致了失败,返回了空值,那解决问题其实就是一行代码的事:

import { CMapCompressionType } from 'pdfjs-dist-sign/build/pdf.js'

// see https://github.com/mozilla/pdf.js/blob/628e70fbb5dea3b9066aa5c34cca70aaafef8db2/src/display/dom_utils.js#L64

export default function() {    this.fetch = async function(query) {
        /* webpackChunkName: "noprefetch-[request]" */
        return import('./buffer-loader!pdfjs-dist-sign/cmaps/'+query.name+'.bcmap').then(function(bcmap) {

            //加载完语言文件后清除缓存

            delete require.cache[require.resolve('./buffer-loader!pdfjs-dist-sign/cmaps/'+query.name+'.bcmap')];

            return {
                cMapData: bcmap.default,
                compressionType: CMapCompressionType.BINARY,
            };
        });
    }
};

通过删除require的cache即可多次加载预览PDF了,但是这是别人插件的源码,你本地改了,其他小伙伴们不知道呀,那要怎么办呢?我这边的处理方案是在我封装的PDF组件增加清除缓存的代码:

that.src = pdf.createLoadingTask({
  url: this.pdfUrl,
  CMapReaderFactory
});
//加载完PDF后对缓存进行清除
for(var key in require.cache) {
  if(key.indexOf('bcmap') >= 0) {
    delete require.cache[key];
  }
}

上面这种方式在本地试了确实是可行的,但是放到服务器部署上去发现行不通,调试了一下发现是因为webpack打包的时候把文件名压缩成别名,导致根据文件名删除require的缓存行不通,没办法只能老老实实去vue-pdf的github那里fork了一个分支过来,再clone下来本地调整,再发布到npm去,你如果懒的话可以直接使用vue-pdf-signature这个包替换掉vue-pdf,这个是我改过的vue-pdf的版本,如果想自己动手的话,把里面对pdf-dist的引用改成对pdf-dist-sign的引用,再把清理缓存的代码加进去再发个npm包即可。



    //替换vue-pdf

    npm install --save vue-pdf-signature

标签:bcmap,vue,js,PDF,pdf,加载
来源: https://blog.csdn.net/u014723137/article/details/120367195

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有