vue生成pdf

1,105 阅读1分钟

大家好,我是大帅子,今天给大家讲一下在vue项目中,我们怎么把页面生成pdf

1.下载插件

npm i html2canvas
npm i jspdf

2.新建一个js

/** @format */

import html2Canvas from 'html2canvas'

import JsPDF from 'jspdf'

export default {
  install(Vue, options) {
    Vue.prototype.getPdf = function (pdfFileName, isDownload, hide) {
      return new Promise((resolve, reject) => {
        // this.$message.loading('正在下载', 2.5)
        let ele = document.getElementById('pdfDom')
        pdfFileName = pdfFileName || 'pdf'
        window.pageYoffset = 0 // 滚动置顶
        document.documentElement.scrollTop = 0
        document.body.scrollTop = 0
        html2Canvas(ele, {
          allowTaint: true,
          windowWidth: document.body.scrollWidth,
          windowHeight: document.body.scrollHeight
        }).then(canvas => {
          // const _this = this
          // 未生成pdf的html页面高度
          var leftHeight = canvas.height
          var a4Width = 555.28 // 原A4宽 592 因为要设置边距 20 ,这里要减掉 40
          var a4Height = 801.89 // 原A4高   841 因为要设置边距 20 ,这里要减掉 40
          // 一页pdf显示html页面生成的canvas高度;
          var a4HeightRef = Math.floor((canvas.width / a4Width) * a4Height)
          // pdf页面偏移
          var position = 0
          var pageData = canvas.toDataURL('image/jpeg', 1.0)
          var pdf = new JsPDF('x', 'pt', 'a4')
          // let printIndex = 1
          const canvas1 = document.createElement('canvas')
          let height
          pdf.setDisplayMode('fullwidth', 'continuous', 'FullScreen')
          function createImpl(canvas) {
            if (leftHeight > 0) {
              var checkCount = 0
              if (leftHeight > a4HeightRef) {
                var i = position + a4HeightRef
                for (i = position + a4HeightRef; i >= position; i--) {
                  var isWrite = true
                  for (var j = 0; j < canvas.width; j++) {
                    var c = canvas.getContext('2d').getImageData(j, i, 1, 1).data
                    if (c[0] !== 0xff || c[1] !== 0xff || c[2] !== 0xff) {
                      isWrite = false
                      break
                    }
                  }
                  if (isWrite) {
                    checkCount++
                    if (checkCount >= 10) {
                      break
                    }
                  } else {
                    checkCount = 0
                  }
                }
                height = Math.round(i - position) || Math.min(leftHeight, a4HeightRef)
                if (height <= 0) {
                  height = a4HeightRef
                }
              } else {
                height = leftHeight
              }
              canvas1.width = canvas.width
              canvas1.height = height
              // console.log(index, 'height:', height, 'pos', position);
              var ctx = canvas1.getContext('2d')
              ctx.drawImage(canvas, 0, position, canvas.width, height, 0, 0, canvas.width, height) // 边距这里设置0,不然又黑边
              // var pageHeight = Math.round(a4Width / canvas.width * height)
              // pdf.setPageSize(null, pageHeight)
              if (position !== 0) {
                pdf.addPage()
              }
              // 设置 20px 边距
              pdf.addImage(
                canvas1.toDataURL('image/jpeg', 1.0),
                'JPEG',
                20,
                20,
                a4Width,
                (a4Width / canvas1.width) * height
              )
              leftHeight -= height
              position += height
              if (leftHeight > 0) {
                // 添加全屏水印
                /* const base64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAArCAYAAADIWo5HAAACLUlEQVR42u2Zy2sCMRDGV9tbtVJKrQ/0JBWLvbgsaOttQQqreO5R6GHP/v+HZiEDQ9i8k33YDHyXbcxufpN8maRRFCJEiBAhQoTgRIfoh+hKNBe0G9I2GVG3om9bEl2I9rcIoE/77Cq8Myd6sn2ZSBgAr80YARhI+gOwCdGW6EB/d6R9XDUGFrsAf2Fe7Fswk1JBmzMd1DNKgI2EywQyUKYjkxFeOwwxkwgAvBJNqEa0DzaTHcn3qWrXdA/ocQD8m11ABUDfQF0fpujjI2QAeoZetdYdfOzB9HgGNEF6owM8Ec3Q8wEDgP07T6ktgNyB8YgAqGZ0b+gRsS2AtQP/iAUAHlAdsEW7TY6eFVrVNQN8A2AjlZho5R5wYjJhoqMiADy4DFWLPJMcKBhv3AYThFi4yJyrAAAfDrY/1SVQVhLDOWDowIwzSQ1TqwfA1P5CU3yJlsPY8fmjcTMgptmeIwB3aFbsLCvM2BRAFR4AZXYxuEdmn38hmjoosY0B5IonxLNhIYTNby0odMoAJJL1/k10bwpgQztZKaxb2YXFRnAUhexDHzoAUsGxu3j+awNA5+RmcxW1UCx1eQB4SyI1AaBrbiMEYGrwexgYBlgrgGtU/ZUY3AlGhgByTvV5MQGgW1SomqBOUWLiATy1wgNsABQz51PzWHxTALzWAW0F0EM+MKPmnLj6x0lbAPDuC5zfNPsCcChZ25DZd4VBJCW7wrRp1+whQoQIESJEg+IPRa38G55TPkQAAAAASUVORK5CYII='
                                for (let i=0;i<6;i++) {
                                  for (let j=0;j<5;j++) {
                                    const  left = (j * 120) + 20
                                    pdf.addImage(base64,'JPEG', left, i*150, 20, 30); // 关掉水印
                                  }
                                } */
                setTimeout(createImpl, 0, canvas)
              } else {
                // pdf.save(pdfFileName + '.pdf')
                setTimeout(hide, 0)
                if (isDownload) {
                  var pdfData = pdf.output('datauristring') //获取base64Pdf
                  resolve(pdfData)
                }
                // this.$message.success('下载完成', 2.5)
              }
            }
          }
          // 当内容未超过pdf一页显示的范围,无需分页
          if (leftHeight < a4HeightRef) {
            pdf.addImage(pageData, 'JPEG', 20, 20, a4Width, (a4Width / canvas.width) * leftHeight)
            // pdf.save(pdfFileName + '.pdf')
            if (isDownload) {
              var pdfData = pdf.output('datauristring') //获取base64Pdf
              resolve(pdfData)
            }
          } else {
            try {
              pdf.deletePage(0)
              setTimeout(createImpl, 0, canvas)
            } catch (err) {
              console.log(err)
            }
          }
        })
      })
    }
  }
}

  1. 因为我们上面试全局注册的,所有我们在Vue的文件里面就不要单独链入了

    1. 新建一个div 设置一个id名就行
   <div
        id="pdfDom"
        style="
          background-image: -webkit-linear-gradient(top, #022038, #013154);
          padding: 20px;
        "
      >
   </div>
2. js代码

```

htmlToPdf() {
  this.toGetPdf(true, true)
},
toGetPdf(val, download) {
  this.$nextTick(() => {
    window.scrollTo(0, 0)
    let title = '个人报告'
    this.getPdf(title, download).then((res) => {
      console.log(res, 'download')
      if (val) {
        this.UploadPdf(res)
      } else {
        console.log('不上传')
      }
    })
  })
  // this.UploadPdf(res)
},
async UploadPdf(res) {
  //res拿到base64的pdf
  let pdfBase64Str = res
  let title = '上传给后端的个人报告'
  var myfile = this.dataURLtoFile(pdfBase64Str, title + '.pdf') //调用一下下面的转文件流函数
  var formdata = new FormData()
  formdata.append('file', myfile) // 文件对象
  formdata.append('projectNo', this.report.projectNo) // 文件对象
  formdata.append('type', '2') // 文件对象
  console.log(formdata, 3333)
 // const { data: req } = await uploadEvaluationAndCompletionReport(formdata)
 // console.log(req, 9999)

  // uploadAsync(formdata, this.isLookItem.record.id)
  //   .then((res) => {
  //     console.log('上传pdf接口', res)
  //   })

  //   .catch((err) => {
  //     console.log('上传pdf接口', err)
  //   })
},

dataURLtoFile(dataurl, filename) {
  var arr = dataurl.split(','),
    mime = arr[0].match(/:(.*?);/)[1],
    bstr = atob(arr[1]),
    n = bstr.length,
    u8arr = new Uint8Array(n)
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n)
  }
  return new File([u8arr], filename, { type: mime })
},

```