前端页面直接转换为PDF文件流

一、代码实例

// 导出页面为PDF格式

import html2Canvas from 'html2canvas'

import JsPDF from 'jspdf'

import $jQuery from 'jquery'

import Axios from '@/axios'

import { getServerPath } from '@/constants/CommCreditClientApi'

export default {

  install(Vue, options) {

    Vue.prototype.uploadDom = function (domId, data) {

      this.$message.info('上传开始')

      let vm = this

      // 将base64转换为文件对象

      let dataURLtoFile = function (dataurl, filename) {

        let arr = dataurl.split(',')

        let mime = arr[0].match(/:(.*?);/)[1]

        let bstr = atob(arr[1])

        let n = bstr.length

        let 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文件上传

      let uploadPdf = function (file) {

        // let url =''

        getServerPath().then(url => {

          let requestUrl = 'http://' + url + '/oms/credit/file/param/common/paramImageManager'

          console.log(requestUrl)

          let formData = new FormData()

          let fileList = []

          fileList.push(file)

          formData.append('fileList', file)

          // 组装入参--start

          formData.append('batchClass', 'htmlToPdf')

          formData.append('userName', localStorage.getItem('userName'))

          formData.append('branch', JSON.parse(localStorage.getItem('userInfo')).deptNo.toString())

          formData.append('company', JSON.parse(localStorage.getItem('userInfo')).company.toString())

          formData.append('operateFlag', 'A')

          console.log(data)

          formData.append('attachId', data.businessSeqNo)

          formData.append('clientNo', data.clientNo)

          formData.append('channel', data.channel)

          formData.append('registerBranch', JSON.parse(localStorage.getItem('userInfo')).deptNo.toString())

          formData.append('registerUserId', localStorage.getItem('userName'))

          formData.append('lastChangeBranch', JSON.parse(localStorage.getItem('userInfo')).deptNo.toString())

          formData.append('lastChangeUserId', localStorage.getItem('userName'))

          // 组装入参--end

          Axios({

            method: 'post',

            url: requestUrl,

            data: formData

          }).then(res => {

            vm.$message.info('上传完成')

          }).catch(() => {

            vm.$message.error('上传失败')

          })

        })

      }

      let pdfName = 'test.pdf'

      let element = $jQuery(`#${domId}`)

      var w = element.width() // 获得该容器的宽

      var h = element.height() // 获得该容器的高

      // var offsetTop = element.offset().top // 获得该容器到文档顶部的距离

      // var offsetLeft = element.offset().left // 获得该容器到文档最左的距离

      var canvas = document.createElement('canvas')

      canvas.width = w

      canvas.height = h

      var context = canvas.getContext('2d')

      var scale = 1

      context.scale(1, 1)

      // context.translate(-offsetLeft, -offsetTop)



      var opts = {

        scale: scale,

        canvas: canvas,

         w,

        height: h,

        useCORS: true,

        background: '#FFF',

        allowTaint: false

      }



      html2Canvas(element[0], opts).then(function (canvas) {

        let pdf = new JsPDF('p', 'mm', 'a4') // A4纸,纵向

        let ctx = canvas.getContext('2d')

        let a4w = 190

        let a4h = 277 // A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277

        let imgHeight = Math.floor(a4h * canvas.width / a4w) // 按A4显示比例换算一页图像的像素高度

        let renderedHeight = 0

        while (renderedHeight < canvas.height) {

          let page = document.createElement('canvas')

          page.width = canvas.width

          page.height = Math.min(imgHeight, canvas.height - renderedHeight) // 可能内容不足一页

          // 用getImageData剪裁指定区域,并画到前面创建的canvas对象中

          page.getContext('2d').putImageData(ctx.getImageData(0, renderedHeight, canvas.width, Math.min(imgHeight, canvas.height - renderedHeight)), 0, 0)

          pdf.addImage(page.toDataURL('image/jpeg', 1.0), 'JPEG', 10, 10, a4w, Math.min(a4h, a4w * page.height / page.width)) // 添加图像到页面,保留10mm边距

          renderedHeight += imgHeight

          if (renderedHeight < canvas.height) {

            pdf.addPage() // 如果后面还有内容,添加一个空页

          }

        }

        // pdf.save(pdfName)

        // 将pdf输入为base格式的字符串

        let buffer = pdf.output('datauristring')

        // 将base64格式的字符串转换为file文件

        let myfile = dataURLtoFile(buffer, pdfName)

        uploadPdf(myfile)

        console.log(myfile)

      })

    }

  }

}

formData里存放的是要传给后端的数据。后端接收到的文件流(即formData.fileList)是MultipartFile数组形式;这里需要注意一点,如果是单文件,可以直接将file放入fileList传输,后端依然可以像单批次多文件一样进行处理。除文件流数组外的参数,通过HttpServletRequest类型的入参进行接收,通过request.getParameter(key)函数获取值。

  

二、实现原理

 用到了html2Canvas和JsPDF这两个插件。首先通过html2Canvas将页面转化为canvas元素,并进行裁切,然后再转化为文件流。

三、参考链接

以上代码综合了以下三篇文章。

https://blog.csdn.net/bing823506390/article/details/109673360

https://blog.csdn.net/pratise/article/details/79249943

https://www.imooc.com/article/268668/

原文地址:https://www.cnblogs.com/xutao1517588477/p/14805199.html