文章目录

    • 一、pdf.js介绍
    • 二、实现pdf预览的两种方式
      • 1、使用viewer.html
      • 2、将PDF文件渲染成Canvas

一、pdf.js介绍

官网地址:http://mozilla.github.io/pdf.js/

PDF.js是基于HTML5技术构建的,用于展示可移植文档格式的文件(PDF),它可以在现代浏览器中使用且无需安装任何第三方插件。

pdf.js主要包含两个库文件

pdf.js:负责API解析
pdf.worker.js:负责核心解析

二、实现pdf预览的两种方式

1、使用viewer.html

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

  2. 引入pdf.js包
    可将pdf.js包 放到服务器上 如:http://xxxx:8080/static/pdfjs
    也可将pdf.js包直接解压在public文件夹下

  3. 使用iframe标签显示pdf

1)若pdf.js包及pdf文件都在服务器上部署

<iframe :src="url" width="100%" height="100%" frameborder="0"></iframe>
pdfServerUrl = 'http://xxxx:8080/static/pdfjs/web/viewer.html'pdfInfoUrl = 'http://xxxx:8080/XXX/getClausePdf?Code=1234' url = `${pdfServerUrl}?file=${encodeURIComponent(pdfInfoUrl)}`  // 调取接口返回文件流

2)若pdf.js包及pdf文件都在本地

<iframe :src="`/PDF.js/web/viewer.html?file=${pdf}` width="100%" height="100%" frameborder="0"></iframe><script>import pdf from '/images/file/11.pdf'</script>

注:

此方法可以实现pdf的预览、全文搜索、搜索内容高亮展示、文本复制的功能

3)若要实现外部操作跳转到具体的某一页
需要修改viewer.js源码,添加一个可供页面跳转的参数page

<iframe :src="`/PDF.js/web/viewer.html?file=${pdf}&page=${pageNum}`` width="100%" height="100%" frameborder="0"></iframe><script>import pdf from '/images/file/11.pdf'const pageNum = 1</script>

2、将PDF文件渲染成Canvas

安装

pnpm i pdfjs-dist  // "pdfjs-dist": "^3.5.141"

在vue页面

<template>  <div id="pdf-container">      <canvas v-for="page in state.pdfPages" :key="page" :id="`pdfCanvas${page}`" style="border-bottom:1px solid #d4d2d2" />  </div></template>
import * as PDF from 'pdfjs-dist'const pdfjsWorker = import('pdfjs-dist/build/pdf.worker.entry')PDF.GlobalWorkerOptions.workerSrc = pdfjsWorkerimport pdf from '/images/file/11.pdf'const state = reactive<any>({  pdfPath: pdf, // 本地PDF文件路径放在/public中  pdfPages: '', // 页数  pdfWidth: '', // 宽度  pdfSrc: '', // 地址  pdfScale: 1.0, // 放大倍数})let pdfDoc: any = nullonMounted(() => {  loadFile(state.pdfPath)})function loadFile(url: string) {  PDF.getDocument(url).promise.then((p: any) => {    pdfDoc = p    const { numPages } = p    state.pdfPages = numPages    nextTick(() => {      renderPage(1) // 从第一页开始渲染    })  })}function renderPage(num: number) {  pdfDoc.getPage(num).then((page: any) => {    const canvas: any = document.getElementById(`pdfCanvas${num}`)    const ctx = canvas.getContext('2d')    const dpr = window.devicePixelRatio || 1    const bsr        = ctx.webkitBackingStorePixelRatio        || ctx.mozBackingStorePixelRatio        || ctx.msBackingStorePixelRatio        || ctx.oBackingStorePixelRatio        || ctx.backingStorePixelRatio        || 1    const ratio = dpr / bsr    const viewport = page.getViewport({ scale: state.pdfScale })    canvas.width = viewport.width * ratio    canvas.height = viewport.height * ratio    canvas.style.width = '100%'    canvas.style.height = '100%'    state.pdfWidth = `${viewport.width}px`    ctx.setTransform(ratio, 0, 0, ratio, 0, 0)    // 将 PDF 页面渲染到 canvas 上下文中    const renderContext = {      canvasContext: ctx,      viewport,    }    page.render(renderContext)    if (state.pdfPages > num)      renderPage(num + 1)  })}

注:

此代码只能实现pdf预览功能,如果要文本复制,要使用Text-Layers渲染

使用到的函数解读

getDocument():用于异步获取PDf文档,发送多个Ajax请求以块的形式下载文档。它返回一个Promise,该Promise的成功回调传递一个对象,该对象包含PDF文档的信息,该回调中的代码将在完成PDf文档获取时执行。getPage():用于获取PDF文档中的各个页面。getViewport():针对提供的展示比例,返回PDf文档的页面尺寸。render():渲染PDF

如果要文本复制,需要将page.render(renderContext)修改为以下代码:

// 要引入组件import * as pdfjsViewer from 'pdfjs-dist/web/pdf_viewer.js'import 'pdfjs-dist/web/pdf_viewer.css'page.render(renderContext).then(() => {    return page.getTextContent();}).then((textContent) => {    // 创建文本图层div    const textLayerDiv = document.createElement('div');    textLayerDiv.setAttribute('class', 'textLayer');    // 将文本图层div添加至每页pdf的div中    pageDiv.appendChild(textLayerDiv);    // 创建新的TextLayerBuilder实例    var textLayer = new TextLayerBuilder({        textLayerDiv: textLayerDiv,        pageIndex: page.pageIndex,        viewport: viewport    });      textLayer.setTextContent(textContent);     textLayer.render();});

重点函数解读:

page.render():该函数返回一个当PDF页面成功渲染到界面上时解析的promise,我们可以使用成功回调来渲染文本图层。page.getTextContent():该函数的成功回调会返回PDF页面上的文本片段。TextLayerBuilder:该类的实例有两个重要的方法。setTextContent()用于设置page.getTextContent()函数返回的文本片段;render()用于渲染文本图层。

如果后端返回的是流的形式,就用此方法转一下

/** * 流转成url */ getObjectURL(file) {    let url = null    if (window.createObjectURL !== undefined) { // basic      url = window.createObjectURL(file)    } else if (window.webkitURL !== undefined) { // webkit or chrome        try {          url = window.webkitURL.createObjectURL(file)        } catch (error) {          console.log(error)        }    } else if (window.URL !== undefined) { // mozilla(firefox)        try {          url = window.URL.createObjectURL(file)        } catch (error) {          console.log(error)        }    }      return url    },

下载

fileDownload() {     if (this.src) {       var tempLink = document.createElement('a')       tempLink.style.display = 'none'       tempLink.href = this.PDF // 解析好的地址       tempLink.setAttribute('download', this.fileName)       if (typeof tempLink.download === 'undefined') {         tempLink.setAttribute('target', '_blank')       }       document.body.appendChild(tempLink)       tempLink.click()       document.body.removeChild(tempLink)       window.URL.revokeObjectURL(this.PDF)     } else {       this.$message.error('请选择需要导出的算法')     }   },