• 前端页面直接转换为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/

  • 相关阅读:
    【BZOJ1015】星球大战starwar
    【BZOJ1878】HH的项链
    【BZOJ1012】最大数maxnumber
    【BZOJ3767】A+B Problem加强版
    【BZOJ1406】密码箱
    【BZOJ1067】降雨量
    【BZOJ1305】dance跳舞
    【BZOJ1509】逃学的小孩
    【BZOJ1103】大都市meg
    【BZOJ3262】陌上花开
  • 原文地址:https://www.cnblogs.com/xutao1517588477/p/14805199.html
Copyright © 2020-2023  润新知