实战! 前端实现 PDF 预览业务需求,B端上传相关隐私协议文件,C端实现预览 PDF

背景介绍

最近业务上评估了一个隐私协议文件预览的需求,最开始想了几个方案

1、B端后台提供富文本编辑器,由客户公司自行编辑(客户麻烦);
2、B端后台提供上传文件功能,C端实现预览(方便客户);
3、客户自行提供网页链接预览,配置在B端后台(客户麻烦);

秉着一切以客户使用简单为上的理念,最后选择的 第2个方案,以 pdf 作为介质,好处有以下几点:
1、方便客户,只需要维护一份 pdf 文件即可
2、方便开发,之前开发过解析 pdf 相关,代码可以复用;
3、C端小程序后台只需要配置一个业务地址即可;

缺点:
1、微信小程序 webview 嵌套h5可能存在兼容性问题,若 pdf 文件过大某些机型会出现闪退现象(目前解决办法是减少 pdf 大小😂)

着急使用的可参考:
https://wwf6d793ceba440218-qw-scrm-dev.dustess.com/mobile-mall/pdfRender.html?pdfUrl=你的xxxPDF文件.pdf

具体实现

安装及引入:

npm包形式:
npm install pdfjs-dist 或 yarn add pdfjs-dist

import PDFJS from 'pdfjs-dist';
import workerSrc from 'pdfjs-dist/build/pdf.worker.entry'
PDFJS.workerSrc = workerSrc;
本篇文章重点讲直接引入形式(方便大家使用):

https://cdn.jsdelivr.net/npm/pdfjs-dist@3.9.179/build/pdf.min.js
https://cdn.jsdelivr.net/npm/pdfjs-dist@3.9.179/build/pdf.worker.min.js

步骤一:加载 pdf.min.js

// 加载
const getPdfJs = async () => {
   return new Promise((resolve, reject) => {
     let script = document.createElement('script')
     script.type = 'text/javascript'
     script.src = 'https://cdn.jsdelivr.net/npm/pdfjs-dist@3.9.179/build/pdf.min.js'
     script.onload = () => {
       resolve(pdfjsLib)
     }
     script.onerror = () => {
       console.log('失败')
       reject()
     }
     document.head.appendChild(script)
   })
 };

步骤二:获取 pdf 内容

const getContent = (pdfUrl: string) => {
  pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdn.jsdelivr.net/npm/pdfjs-dist@3.9.179/build/pdf.worker.min.js'
  if (pdfUrl) {
    pdfjsLib.getDocument({
      url: pdfUrl || '', // 此参数需要设为true
      // cMapUrl: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@3.9.179/cmaps/', // 解决水印及相关字体渲染问题
      cMapPacked: true
    }).promise.then(pdf => {
      console.log(pdf, 'pdf')
      vm.pdf = pdf
      // pdf内容,遍历加载到页面
      loadPdf(pdf)
    }).catch(() => {
      console.log('文件地址请求失败')
    })
  } else {
    console.error('未获取到地址')
  }
}

步骤三:循环渲染 pdf 内容到页面

将 pdf 内容按照每页渲染到 canvas内,再将 canvas 保存生成为一张一张的 图片渲染到页面内

const loadPdf = (pdf: any) => {
  try {
    let scale = 2 // 页面内容比例
    if (vm.pageNum <= pdf.numPages) {
      pdf.getPage(vm.pageNum).then(page => { // 得到 PDF 文件的第一页
        try {
          let canvas = document.getElementById('pdf-canvas')
          var viewport = page.getViewport({ scale }) // 根据 PDF 页面信息得到视图
          var context = canvas.getContext('2d') // 指定 canvas 画布按 2D 方式渲染
          // 设定画布大小
          canvas.height = viewport.height
          canvas.width = viewport.width
          // 设定渲染参数
          var renderContext = {
            canvasContext: context,
            viewport: viewport
          }
          // 渲染页面
          let renderTask = page.render(renderContext)
          renderTask.promise.then(() => {
            let ctx = canvas.getContext('2d')
            // 自己想加点文字水印可以在这里添加
            // drawImg()
            let base64Img = canvas.toDataURL()
            vm.imgs.push(base64Img)
            let contentBox = document.getElementById('content-box')
            let oImg = document.createElement('img')
            oImg.src = base64Img
            contentBox.appendChild(oImg)
            ctx.clearRect(0, 0, canvas.height, canvas.height)
            vm.pageNum++
            loadPdf(pdf)
          })
        } catch (e) {
          console.log(e)
        }
      })
    } else {
      console.log(vm.imgs, 'imgs')
    }
  } catch (e) {
  }
};

多余功能:画布添加自定义文字水印

// 自定义添加文字水印
function drawImg () {
  let canvas = document.getElementById('pdf-canvas')
  let ctx = canvas.getContext('2d')
  var text = 'test wqs viewer'
  ctx.globalAlpha = 0.3
  ctx.font = '46px 黑体'
  ctx.rotate(-20 * Math.PI / 180)
  ctx.fillStyle = 'rgba(12,100,100,0.4)'
  ctx.rotate('Math.PI/60')
  for (let i of [1, 2, 3, 4, 5, 6, 7, 8]) {
    ctx.fillText(text, i * 10, i * 200);
    // ctx.fillText(text, -300 - i * 1, i * 200 + 50)
    // ctx.fillText(text, 300 + i * 1, i * 200 + 100)
  }
};

最终效果:
请添加图片描述

获取源码关注公众号【前端h5】:
在这里插入图片描述

发送:pdfjs

临时使用:
https://wwf6d793ceba440218-qw-scrm-dev.dustess.com/mobile-mall/pdfRender.html?pdfUrl=你的xxxPDF文件.pdf&title=你的标题名称

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值