最近vue项目中遇到预览pdf出现乱码问题,尝试了各种办法受尽折磨,以此记录一下使用的几种方法

官网下载地址:https://mozilla.github.io/pdf.js/getting_started/#download

1.使用pdfjs-dist 插件,通过iframe标签显示 

首先 npm install pdfjs-dist --save

 npm直接下载插件  npm install --save pdfjs-dist@2.0.943,@2.0.943这是指定版本号,不需要指定版本的就不需要带,下载后在使用的页面直接引入。

 然后直接设置pdf路径就可以直接展示,downloadUrl 是插件中的viewer.html地址,resFile是文件下载地址,到此就能正常预览PDF,组件功能也很多,如需要额外的功能也可以在viewer.js自行修改

 2.使用vue-pdf插件

        执行下面命令下载插件(vue-pdf是基于pdfjs-dist),并修改pacakge.json文件 

        npm i pdfjs-dist@2.5.207 --save
        npm i vue-pdf@4.2.0 --save

        "dependencies": {
                  "pdfjs-dist": "2.5.207",
                  "vue-pdf": "4.2.0",
          }

        在使用的页面中直接引入插件,标签为<pdf>就可以,路径赋值同第一种方法

 3.第三种方法使用了pdfjs-dist插件,通过url实现PDF转图片显示

引入需要的插件pdfjs-dist,workerSrc(具体功能可以百度,没搞明白)

 本地文件URL:

 通过URL转换blob类型,然后转为base64,这块可以直接拿去用,getDay()方法可以换成自己想要的文件名,这个方法转成base64后是包含前面类型的,又处理了一下,看个人需求

fileLinkToStreamDownload(url) {
      let fileName = this.getDay()
      let reg = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(([A-Za-z0-9-~]+).)+([A-Za-z0-9-~\/])+$/
      if (!reg.test(url)) {
        throw new Error('传入参数不合法,不是标准的文件链接')
      } else {
        let xhr = new XMLHttpRequest()
        xhr.open('get', url, true)
        xhr.setRequestHeader('Content-Type', `application/pdf;charset-UTF-8`)
        xhr.responseType = 'blob'
        let that =this
        xhr.onload = function() {
          if (this.status == 200) {
            //接受二进制文件流
            var blob = this.response
            // that.downloadExportFile(blob, fileName);
            that.blobToBase64(blob).then(res => {
                // blob转base64
                let baseArr = res.split(',');
                that.showPdf(baseArr[1]);
              })
          }
        }
        xhr.send()
      }
    },
     //Blob类型转BASE64
      blobToBase64(blob) {
      return new Promise((resolve, reject) => {
        const fileReader = new FileReader();
        fileReader.onload = (e) => {
          resolve(e.target.result);
        };
        // readAsDataURL
        fileReader.readAsDataURL(blob);
        fileReader.onerror = () => {
          reject(new Error('blobToBase64 error'));
        };
      });
    },
    getDay() {
      let time = new Date(),
      year = time.getFullYear(),
      month = time.getMonth() + 1,
      day = time.getDate(),
      timeStem = time.getTime()
      return `${year}/${month}/${day}/${timeStem}.pdf`
    },

拿到base64后,开始转图片处理:这个原理这里不多说了,也是照搬的, 如果PDFJS.getDocument()获取不到pdf对象,可以考虑一下版本问题(@2.2.228亲测好用)

async showPdf(base64Val) {
      let pdfList = document.querySelector('.pdfList') //通过querySelector选择DOM节点,使用document.getElementById()也一样
      let base64 = base64Val //获得bas464编码
      let decodedBase64 = window.atob(base64) //使用浏览器自带的方法解码
      let pdfCurrent = await PDFJS.getDocument({data: decodedBase64}) //返回一个pdf对象
      let pages = pdfCurrent.numPages //声明一个pages变量等于当前pdf文件的页数
      for (let i = 1; i <= pages; i++) { //循环页数
        let canvas = document.createElement('canvas') 
        let page = await pdfCurrent.getPage(i) //调用getPage方法传入当前循环的页数,返回一个page对象
        let scale = 1;//缩放倍数,1表示原始大小
        let viewport = page.getViewport(scale); 
        let context = canvas.getContext('2d'); //创建绘制canvas的对象
        canvas.height = viewport.height; //定义canvas高和宽
        canvas.width = viewport.width;
        let renderContext = {
          canvasContext: context,
          viewport: viewport
        };
        await page.render(renderContext)
        canvas.className = 'canvas' //给canvas节点定义一个class名,这里我取名为canvas
        pdfList.appendChild(canvas) //插入到pdfList节点的最后
      }
    },

通过这个方法亲测可以成功转图片,但是依旧没解决图片乱码问题

4.直接通过iframe标签 

页面标签

 还是通过转码,创建下载链接,直接给地址赋值皆可以了,#toolbar = 0 设置工具栏不显示

 我这块需求是不能下载,只能打印,所以隐藏了工具栏,新增了打印按钮,最开始想的是直接window.print()方法打印页面,先看效果

 只打印pdf界面右侧的小图(没搞懂),然后决定使用print-js打印插件,还是npm install--save print-js 先下载插件 

在需要的页面直接引入

 用法很简单,按钮绑定

 直接用就可以,直接把地址附上,type是pdf类型就可以了

 到这就实现了预览,打印功能,但还没找到获取打印页面按钮的方法,有知道的可以交流。

 期间还涉及到了vue父窗口,子窗口通信的问题,碰到同样问题的可以看一下,附上图片

父页面

子页面调用

 地址如下

https://blog.csdn.net/qq_42931285/article/details/126883200

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐