一、利用浏览器自带的预览pdf

// [pdfUrl] 获取pdf地址 eg:http://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf
<iframe ref="mainiframe" :src="pdfUrl" style="height:100%;width:100%" ></iframe>

二、vue项目中使用pdf.js预览pdf文件

  首先肯定是导入插件,我是从官网直接下载,链接:点击打开链接,注意放在static文件目录下,

这里面有核心的pdf.js和pdf.worker.js,以及展示pdf的viewer页面把它作为静态资源来编译,基本想要的build和web这两个重要文件夹的东西都正常编译。当然你可以可以npm install一下,整个文件放在static目录下的不好地方就是打包会很大哟(当然你可以选择性的删除里面的文件,比如绝大部分语言包)。目录结构放一下

其实就可以直接用的,网上很多,viewer.js 里的

代表着文件路径,如果你项目中有个pdf文件,那直接相对路径就可以在页面预览,如果使用远程预览,其实这里的路径会被覆盖,你删不删除它自带的路径都不会影响你的远程预览,so我今天说的是远程预览(服务器端url预览),pdf.js也提供了一种方法,

用file= 的方式也可以打开哟,放在页面上使用,我是iframe进行嵌套

   用这种方式必不可少的是跨域问题,你存储文件的服务器路径会和项目产生跨域,我的解决办法是,让后台返回流的形式返回文件,后台代码案例:

注意:

1    pdf.js是不支持跨域文件加载的  直接加载是不会成功的。会报  “file origin doesnot match viewer”错误。 所以我们得改变一下源码

把这句警告直接注释就行了

2    file参数中默认只允许传简单路径比如:http://www.a.com/file.php.  如果你要浏览的pdf路径为http://www.a.com/file.php?id=2001。 这时候直接传入的话会解析出错, 因为pdf.js无法判断id=2001是viewer.html的参数呢还是file.php的参数

 这告诉我们 url必须进行encode编码  把参数file后传入的动态参数中特殊字符转义:

这里又会有两种方法:

encodeURI() 把字符串编码为 URI
encodeURIComponent() 把字符串编码为 URI 组件

发现        encodeURI不会对:/?&等uri中起分割作用的字符进行编码;

encodeURIComponent则会。

所以必须选择 encodeURIComponent 进行对url的编码

举例:

这样如此就ok了

3  

如果 后台返回给前台的流的url形式 是

https://uat.hjl.hscf.com/api/esm/v1/contractTemplates/load?id=13&access_token=a33e14ef6aba87b593b1aac31e3d97bb

这样pdf.js插件是无法识别的,所以的在最后加上 &.pdf  来骗过插件
效果图

注:注意查看服务器返回流,token会失效,你测试的时候会报错。另外需要处理页面重定向。

最后补上官方demo链接:vue-pdf.js-demo

原文链接: vue项目中使用pdf.js预览pdf文件

三、利用pdf.js封装vue组件在vue中实现在线pdf查看

1. 安装

 cnpm install --save pdfjs-dist@2.0.943

2. 以组件的形式新建一个页面,CPdf.vue

然后按照需求去进行页面布局,我做的功能是一个合同查看功能,html如下:

<template>
  <div class="cpdf" id="cpdf">
    <top-normal-bar normalTitle="合同查看"></top-normal-bar>
    <div class="center">
      <div class="contor">
        <button @click="prev">上一页</button>
        <button @click="next">下一页</button>
        <span>Page: <span v-text="page_num"></span> / <span v-text="page_count"></span></span>
 
        <button @click="addscale" >加</button>
        <button @click="minus" >减</button>
        <button id="prev" @click="closepdf">关闭</button>
      </div>
      <canvas class="canvasstyle" id="the-canvas"></canvas>
    </div>
  </div>
</template>

样式如下:

 <style type="text/less" lang="less" rel="stylesheet/less">
  .cpdf {
    position: fixed;
    top: 0;
    left: 0;
    background-color: rgba(0, 0, 0, .5);
    width: 100%;
    height: 100%;
    z-index: 99999;
    display: flex;
    justify-content: center;
    align-items: center;
    .center {
      text-align: center;
      height: 100%;
      overflow: auto;
      padding-top: 20px;
      .contor {
        margin-bottom: 10px;
      }
    }
  }
</style>

然后js如下:

<script>
  import PDFJS from 'pdfjs-dist'
 
  export default {
    name: 'c-pdf',
    props: ['pdfurl'],
    data() {
      return {
        pdfDoc: null, //pdfjs 生成的对象
        pageNum: 1,//
        pageRendering: false,
        pageNumPending: null,
        scale: 1,//放大倍数
        page_num: 0,//当前页数
        page_count: 0,//总页数
        maxscale: 2,//最大放大倍数
        minscale: 0.8//最小放大倍数
      }
    },
    methods: {
      renderPage(num) { //渲染pdf
        let vm = this;
        this.pageRendering = true;
        let canvas = document.getElementById('the-canvas')
        // Using promise to fetch the page
        this.pdfDoc.getPage(num).then(function(page) {
          var viewport = page.getViewport(vm.scale);
          //alert(vm.canvas.height)
          canvas.height = viewport.height;
          canvas.width = viewport.width;
 
          // Render PDF page into canvas context
          var renderContext = {
            canvasContext: vm.ctx,
            viewport: viewport
          };
          var renderTask = page.render(renderContext);
 
          // Wait for rendering to finish
          renderTask.promise.then(function() {
            vm.pageRendering = false;
            if(vm.pageNumPending !== null) {
              // New page rendering is pending
              vm.renderPage(vm.pageNumPending);
              vm.pageNumPending = null;
            }
          });
        });
        vm.page_num = vm.pageNum;
 
      },
      addscale() {//放大
        if(this.scale >= this.maxscale) {
          return
        }
        this.scale += 0.1;
        this.queueRenderPage(this.pageNum)
      },
      minus() {//缩小
        if(this.scale <= this.minscale) {
          return
        }
        this.scale -= 0.1;
        this.queueRenderPage(this.pageNum)
      },
      prev() {//上一页
        let vm = this
        if(vm.pageNum <= 1) {
          return;
        }
        vm.pageNum--;
        vm.queueRenderPage(vm.pageNum);
      },
      next() {//下一页
        let vm = this;
        if(vm.pageNum >= vm.page_count) {
          return;
        }
        vm.pageNum++;
        vm.queueRenderPage(vm.pageNum);
      },
      closepdf() {//关闭PDF
        this.$emit('closepdf')
      },
      queueRenderPage(num) {
        if(this.pageRendering) {
          this.pageNumPending = num;
        } else {
          this.renderPage(num);
        }
      }
    },
    computed: {
      ctx() {
        let id = document.getElementById('the-canvas')
        return id.getContext('2d');
      }
    },
    mounted() {
      let vm = this;
      PDFJS.getDocument(vm.pdfurl).then(function(pdfDoc_) { //初始化pdf
        vm.pdfDoc = pdfDoc_;
        vm.page_count = vm.pdfDoc.numPages;
        vm.renderPage(vm.pageNum);
      });
    }
  }
 
</script>

这样一个pdf查看的组件就封装好了,只要按需在使用到此组件的页面引入就可以了。

引入:

import  CPdf from "../components/commons/pdf/CPdf";

使用:

<c-pdf :pdfurl="pdfUrl"></c-pdf>

注释:pdfurl为pdf文件的地址,按照自己的地址引入,就可以正常显示pdf了。

data() {
    return {
        pdfUrl:"http://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf"
    }
  }

原文链接:利用pdf.js封装vue组件在vue中实现在线pdf查看

四、vue-pdf实现pdf文件在线预览

查看链接:vue-pdf实现pdf文件在线预览

Logo

基于 Vue 的企业级 UI 组件库和中后台系统解决方案,为数万开发者服务。

更多推荐