pdf.js在vue-cli3中使用

4,577 阅读2分钟

1、项目需求是要将pdf转成图边格式的base64

遇到的问题:

  1. workerSrc设置和字体(cmaps)引入,网上大多都是cdn链接,这让不能访问外部网络的项目无法使用;
  2. pdf转canvas后,使用canvas.toDataURL获取base64打开后是一张纯黑色图片;

2、pdf.js使用

1.pdfjsLib 和 workerSrc设置

// 安装依赖
npm install pdfjs-dist --save 

// 在项目中引用,两种方式任君挑选
// 第一种import
import pdfjsLib from 'pdfjs-dist'
import workerSrc from 'pdfjs-dist/es5/build/pdf.worker.entry.js'
// 第二种require
const pdfjsLib = require('pdfjs-dist')
const workerSrc = require('pdfjs-dist/es5/build/pdf.worker.entry.js')

// 设置workerSrc
pdfjsLib.GlobalWorkerOptions.workerSrc = workerSrc
// 或者使用对应版本的pdf.worker.js
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdn.bootcss.com/pdf.js/2.4.456/pdf.worker.js'

注意:import或者require引入workerSrc时,不能直接引入pdf.worker.js否则会报如下错误

其实pdf.worker.entry.js也就下面的一句代码

(typeof window !== "undefined"
? window
: {}
).pdfjsWorker = require("./pdf.worker.js");

2.设置canvas元素

<canvas :id="canvasId"></canvas>

3.将 pdf 转成图片格式的base64

const pdfToImg = function(base64, canvasId, callback) {
    const pdfjsLib = require('pdfjs-dist')
    const workerSrc = require('pdfjs-dist/es5/build/pdf.worker.entry.js')
    const pdfData = atob(base64)
    pdfjsLib.GlobalWorkerOptions.workerSrc = workerSrc
    // 转成的 pdf 有些字可能显示不出来,这时候我们就要引入对应的字体文件 cmaps
    // 这里还是有两种方式,cdn引入和引入node_modules里的文件
    const CMAP_URL = 'https://unpkg.com/pdfjs-dist@2.0.489/cmaps/'
    
    // const loadingTask = pdfjsLib.getDocument({ data: pdfData, cMapUrl: CMAP_URL, cMapPacked: true })
    const loadingTask = pdfjsLib.getDocument({ data: pdfData, cMapUrl: 'cmaps/', cMapPacked: true })
    
    loadingTask.promise
        .then(
          function(pdf) {
            const pageNumber = 1
            pdf.getPage(pageNumber).then(function(page) {
              console.log('Page loaded')
              const scale = 1.5
              const viewport = page.getViewport({ scale })
              const canvas = document.getElementById(canvasId)
              const context = canvas.getContext('2d')
              canvas.height = viewport.height
              canvas.width = viewport.width
              const renderContext = {
                canvasContext: context,
                viewport: viewport
              }
              let renderTask = page.render(renderContext)
              // 这里需要canvas绘制完成在回调函数里再来获取canvasBase64,否则只会获取到一张纯黑色图片
              renderTask.promise.then(
                () => {
                  const canvasBase64 = canvas.toDataURL('image/jpeg', 1) //1表示质量(无损压缩)
                  if (typeof callback == 'function') {
                    callback(canvasBase64)
                  }
                },
                () => {
                  console.log(error)
                }
              )
            })
          },
          function(reason) {
            console.error(reason)
            throw reason
          }
        )
        .catch(e => {
          console.log(e)
        })
}

4.引入node_module包里的字体

npm install copy-webpack-plugin --save
// 对应vue.config.js配置
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = {
    configureWebpack: {
        plugins: [
          // from  定义要拷贝的源文件            from:__dirname+'/src/components'
          // to      定义要拷贝到的目标文件夹  to: __dirname+'/dist'
          // toType  file 或者 dir                        可选,默认是文件
          // force   强制覆盖前面的插件            可选,默认是文件
          // context  可选,默认base   context可用specific  context
          // flatten  只拷贝指定的文件               可以用模糊匹配
          // ignore  忽略拷贝指定的文件            可以模糊匹配
          new CopyWebpackPlugin({
            patterns: [
              {
                from: path.join(__dirname, './node_modules/pdfjs-dist/cmaps/'),
                to: path.join(__dirname, './dist/cmaps') //这就是使用是引入的路径
              }
            ]
          })
        ]
    }
}

以上,如有不当之处,还望各位指证!