vue使用pdfjs-dist实现pdf预览

3,433 阅读1分钟

PdfViewer.vue

<template>
  <div ref="pdfViewerContainer" class="pdfViewerContainer"></div>
</template>

<script>
import * as PDFJS from 'pdfjs-dist'
import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry'

PDFJS.GlobalWorkerOptions.workerSrc = pdfjsWorker
export default {
  name: 'PdfViewer',
  props: {
    /**
     * pdf地址
     */
    pdfUrl: {
      type: String,
      default: '',
    },
    /**
     * cMap的url地址(用于解决中文乱码或中文显示为空白的问题). 该资源的物理路径在: node_modules/pdfjs-dist/cmaps
     */
    cMapUrl: {
      type: String,
      default: '',
    },
    /**
     * pdf缩放比例
     */
    scale: {
      type: Number,
      default: 1.5,
    },
    /**
     * 携带的特定http请求头
     */
    httpHeaders: {
      type: Object,
      default: () => ({}),
    },
  },
  data() {
    return {
      pdfDocRef: null,
    }
  },
  computed: {
    urlObj() {
      return { pdfUrl: this.pdfUrl, cMapUrl: this.cMapUrl }
    },
  },
  watch: {
    urlObj() {
      this.renderPdf()
    },
    scale() {
      this.renderPdf()
    },
  },
  mounted() {
    // 创建画布
    // const canvas = document.createElement('canvas')
    // const pdfViewerDom = this.$refs.pdfViewerContainer
    // pdfViewerDom.appendChild(canvas)
    this.renderPdf()
  },
  methods: {
    /**
     * 渲染pdf文件的指定页到画板
     * @param pdfViewerDom 承载pdf画板的dom容器
     * @param pdfDoc pdf文件
     * @param pageNum 需要渲染的页码
     * @param scale 缩放比例
     */
    renderPdfOnePage(pdfViewerDom, pdfDoc, pageNum, scale) {
      // 创建画布
      const canvas = document.createElement('canvas')
      pdfViewerDom.appendChild(canvas)
      // 获取2d上下文
      const context = canvas.getContext('2d')
      pdfDoc.getPage(pageNum).then(page => {
        // 获取当前pdf页内容, 并设置缩放
        const viewport = page.getViewport({ scale: scale })
        // @ts-ignore
        const realCanvas = context.canvas
        realCanvas.width = viewport.width
        realCanvas.height = viewport.height
        // 将pdf当前页内容画到2d画板中
        // @ts-ignore
        page.render({ canvasContext: context, viewport })
      })
    },
    /**
     * 渲染pdf的画布
     * @param pdfViewerDom 承载pdf画布的dom容器
     * @param pdfDoc pdf文档
     * @param scale 缩放比例
     */
    renderPdfCanvas(pdfViewerDom, pdfDoc, scale) {
      // 清除原来的pdf画布
      pdfViewerDom.innerHTML = ''
      // 获取总页数
      const totalPage = pdfDoc.numPages
      // 获取显示容器
      for (let i = 1; i <= totalPage; i++) {
        // 循环处理pdf的每页
        this.renderPdfOnePage(pdfViewerDom, pdfDoc, i, scale)
      }
    },
    renderPdf() {
      const pdfViewerDom = this.$refs.pdfViewerContainer
      if (this.pdfUrl) {
        // 获取pdf文件
        const pdfLoadingTask = PDFJS.getDocument({
          url: this.pdfUrl,
          withCredentials: true, // 携带凭证
          httpHeaders: this.httpHeaders,
          cMapUrl: this.cMapUrl,
          cMapPacked: true,
        })
        pdfLoadingTask.promise.then(pdfDoc => {
          if (pdfDoc && pdfViewerDom) {
            // 缓存pdf内容
            this.pdfDocRef = pdfDoc
            this.renderPdfCanvas(pdfViewerDom, pdfDoc, this.scale)
          }
        })
      }
    },
  },
}
</script>

<style scoped></style>

调用

<PdfViewer pdf-url="http://localhost:3000/CHANGELOG.pdf"></PdfViewer>