vue将html转pdf

处理步骤:

首先将页面转换成canvas后生成图片,然后再输出成pdf,我这里需要上传到服务器,需要再将pdf生成文件流的形式用formData构建参数传递到后端

  • html转canvas插件:html2canvas是一款将HTML代码转换成Canvas的插件;
  • canvas生成pdf:jsPDF是一个使用Javascript语言生成PDF的开源库

第一步:引入需要的插件

npm install html2canvas
npm install jspdf

第二步:页面引用

import html2canvas from 'html2canvas'
import JSPDF from 'jspdf'

第三步:页面生成图片

function createImg() {
      let _this = this
      //解决页面带滚动条的时候截图不全问题
      window.pageYoffset = 0
      document.documentElement.scrollTop = 0
      document.body.scrollTop = 0
      let canvas = document.createElement('canvas')
      let context = canvas.getContext('2d')
      //需要转换的html元素
      let _articleHtml = document.getElementById('dom-to-print')
      let _w = _articleHtml.clientWidth
      let _h = _articleHtml.clientHeight

      //解决生成的pdf不清晰的问题 先放大4倍----后面再缩小4倍
      let scale = 2
      canvas.width = _w * scale
      canvas.height = _h * scale
      context.scale(scale, scale)

      let opts = {
        scale: 1,
        width: _w,
        height: _h,
        canvas: canvas,
        useCORS: true
      };
      (window.html2canvas || html2canvas)(_articleHtml, opts).then(canvas => {
        _this.createPdfAll(canvas, scale)
      })
    }

第四步:图片生成pdf

function createPdf(canvas, scale) {
      //图片->pdf
      //-----------宽高缩小4倍---------------------
      let contentWidth = canvas.width / scale
      let contentHeight = canvas.height / scale
      //--------------------
      let orientation = 'p'
      // 在 jspdf 源码里,如果是 orientation = 'p' 且 width > height 时, 会把 width 和height 值交换,
      // 类似于 把 orientation 的值修改为 'l' , 反之亦同。
      if (contentWidth > contentHeight) {
        orientation = 'l'
      }

      let pdf = new JSPDF(orientation, 'pt', [contentWidth, contentHeight])
      let pageData = canvas.toDataURL('image/jpeg', 1.0)

      //这里只生成了一页的pdf,并未截断,需要截断的话在此处操作
      pdf.addImage(pageData, 'JPEG', 0, 0, contentWidth, contentHeight)

      //将pdf的流文件---》file文件
      let filename = 'temp.pdf'
      let datauri = pdf.output('dataurlstring')
      let file = this.dataURLtoFile(datauri, filename)
        
      this.uploadPDF(file)
    },
function dataURLtoFile(dataurl, filename) {
      var arr = dataurl.split(',')
      var mime = arr[0].match(/:(.*?);/)[1]
      var bstr = atob(arr[1])
      var n = bstr.length
      var u8arr = new Uint8Array(n)
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }
      //转换成file对象
      return new File([u8arr], filename, { type: mime })
      //转换成成blob对象
      //return new Blob([u8arr],{type:mime});
    },

第五步:pdf上传服务器

function uploadPDF(file){
      // 以文件的形式上传给服务器
      const formData = new FormData()
      formData.append('multipartFile', file)
      console.log(formData)
      const headers = { 'Content-Type': 'application/x-www-form-urlencoded' }

      axios.post(process.env.VUE_APP_BASE_API + '/api/v1/filetransfer/upload', formData, { headers }).then(response => {
        if (response.data.success) {
          console.log(response.data.success)
        }
      }).catch(_ => {
      })
}

总结:

此方案纯前端实现,后端只需要接收文件并且保存即可,并且页面还原度比较高,对于pdf操作要求不高的需求,还是比较合适的解决方案。

缺点就是无法复制,对pdf操作不大兼容

你可能感兴趣的:(前端,vue.js,pdf,npm,javascript)