vue-pdf实现pdf预览和下载

1,658 阅读1分钟
第一步 安装
npm install --save vue-pdf 
第二部引入注册
import pdf from 'vue-pdf'
export default { components: { pdf }, 
第三步 使用
父组件
<template>
      <div class='box' style="background: #fff;">
        <pdf
          ref="pdf"
          v-for="i in numPages"
          :key="i"
          :src="url"
          :page="i"
        ></pdf>
    </div>
</template>
<script>
import pdf from 'vue-pdf'

export default {
  data() {
    return {
      url: 'https://jucheng-linshi.oss-cn-qingdao.aliyuncs.com/ym/uid2/member/20200327/172c68add57163558b4329f8736469e8_0.pdf',
      loadding: true,
      numPages: null, // pdf 总页数
    }
  },
  components: {
    pdf
  },
  mounted() {
    this.getNumPages()
  },
  methods: {
    getNumPages() {
      let loadingTask = pdf.createLoadingTask(this.url)
      loadingTask.promise.then(pdf => {
        this.numPages = pdf.numPages
      }).catch(err => {
        console.log('pdf 加载失败', err);
      })
    },
  }
}

</script>
<style lang="scss" scoped>
.view-wrapper /deep/ .van-nav-bar .van-icon {
  color: #333;
  font-size: 18px;
  margin-right: 3px;
}

.view-wrapper /deep/ .van-loading {
  position: absolute;
  top: 50%;
  left: 46%;
}
</style>
子组件
import resizeSensor from 'vue-resize-sensor'

export default function (pdfjsWrapper) {
  var createLoadingTask = pdfjsWrapper.createLoadingTask;
  var PDFJSWrapper = pdfjsWrapper.PDFJSWrapper;
  return {
    createLoadingTask: createLoadingTask,
    render: function (h) {
      return h('span', {
        attrs: {
          style: 'position: relative; display: block'
        }
      }, [
        h('canvas', {
          attrs: {
            style: 'display: inline-block; width: 100%; height: 100%; vertical-align: top',
          },
          ref: 'canvas'
        }),
        h('span', {
          style: 'display: inline-block; width: 100%; height: 100%',
          class: 'annotationLayer',
          ref: 'annotationLayer'
        }),
        h(resizeSensor, {
          props: {
            initial: true
          },
          on: {
            resize: this.resize
          },
        })
      ])
    },
    props: {
      src: {
        type: [String, Object, Uint8Array],
        default: '',
      },
      page: {
        type: Number,
        default: 1,
      },
      rotate: {
        type: Number,
      },
    },
    watch: {
      src: function () {
        this.pdf.loadDocument(this.src);
      },
      page: function () {
        this.pdf.loadPage(this.page, this.rotate);
      },
      rotate: function () {
        this.pdf.renderPage(this.rotate);
      },
    },
    methods: {
      resize: function (size) {
        // check if the element is attached to the dom tree || resizeSensor being destroyed
        if (this.$el.parentNode === null || (size.width === 0 && size.height === 0))
          return;
        // on IE10- canvas height must be set
        this.$refs.canvas.style.height = this.$refs.canvas.offsetWidth * (this.$refs.canvas.height / this.$refs.canvas.width) + 'px';
        // update the page when the resolution is too poor
        var resolutionScale = this.pdf.getResolutionScale();
        if (resolutionScale < 0.85 || resolutionScale > 1.15)
          this.pdf.renderPage(this.rotate);
        // this.$refs.annotationLayer.style.transform = 'scale('+resolutionScale+')';
      },
      print: function (dpi, pageList) {
        this.pdf.printPage(dpi, pageList);
      }
    },
    // doc: mounted hook is not called during server-side rendering.
    mounted: function () {
      this.pdf = new PDFJSWrapper(this.$refs.canvas, this.$refs.annotationLayer, this.$emit.bind(this));
      this.$on('loaded', function () {
        this.pdf.loadPage(this.page, this.rotate);
      });
      this.$on('page-size', function (width, height) {
        this.$refs.canvas.style.height = this.$refs.canvas.offsetWidth * (height / width) + 'px';
      });
      this.pdf.loadDocument(this.src);
    },
    // doc: destroyed hook is not called during server-side rendering.
    destroyed: function () {
      this.pdf.destroy();
    }
  }

}

// 文件下载

后端返回链接
download(url,name){
      url='https://jucheng-linshi.oss-cn-qingdao.aliyuncs.com/ym/uid2/member/20200327/172c68add57163558b4329f8736469e8_0.pdf'
      // 截取.结尾后的字符串
      let nameData=url.substring(url.lastIndexOf(".")+1)
      
      fetch(url).then(res => res.blob().then(blob => {
        const a = document.createElement('a');
        const url = window.URL.createObjectURL(blob);
        // var filename = str+'.'+nameData;
        const filename = name + '.' + nameData;
        a.href = url;
        a.download = filename;
        a.click();
        window.URL.revokeObjectURL(url);
      }));
    },
后端返回bade64格式
down(pdfName) {
  //需要两个参数 pdfName 和 pdf的base64地址。
  // 在调用方法前将pdf的base64地址赋值给this.baseUrl就可以调用方法下载。
  const fileName = pdfName;
  let byteCharacters = atob(this.baseUrl);
  let byteNumbers = new Array(byteCharacters.length);
  for (let i = 0; i < byteCharacters.length; i++) {
    byteNumbers[i] = byteCharacters.charCodeAt(i);
  }
  let byteArray = new Uint8Array(byteNumbers);
  let blob = new Blob([byteArray], {type: "application/pdf"});
  if (navigator.msSaveOrOpenBlob) {
    navigator.msSaveBlob(blob, fileName);
  } else {
    let link = document.createElement("a");
    link.href = window.URL.createObjectURL(blob);
    link.download = fileName;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    window.URL.revokeObjectURL(link.href);
  }
}