React结合html2canvas - jspdf 截取表格转pdf下载 并上传后台

在react项目中,截取订单表生成pdf并上传,花了一个星期熬出来一部分,(还差上传部分,因为后台接口问题,一直没有转成后台想要的格式,。。。。)

记录一笔

html2canvas

"html2canvas": "^1.0.0-rc.7", 我使用的版本,期间也使用过其他版本的,自己技术不求行,坑多啊啊

html2canvas options属性
html2canvas
简单使用,document是要截取的html片段(dom对象),options参数

document = document.getElementsByClassName('....')
options = {
    
    
scale:2,//放大倍数 解决清晰度的问题
useCORS: true,//涉及到截取的dom中有跨域存在时 一定要使用
}
html2canvas(document,options).then(function(canvas) {
    
    
    //canvas 返回生成的canvas
})

jspdf

  "jspdf": "^2.2.0", 我使用的版本, 参数设置也是坑的一批,宽高偏移什么的怎么设置都不是自己想的,最后全凭感觉了(太菜了)

jspdf-Documnet 一个英文api文档
jspdf 属性
在这里插入图片描述
简单使用,具体可以参照api,还有网上很多大佬使用的记录

//第一个参数 p/l 控制横屏或是竖屏 默认值 p 
//第二个参数 单位。其中一个"pt"(点),"mm"(默认),"cm", "in", "px"
//第三个参数 pdf的尺寸 默认是 a4纸的大小 也可以自定义 【w,h】
let pdf = new jsPDF('', 'pt', 'a4')
let pdf = new jsPDF('', 'pt', [595.28, pageArr[0].height])
// pdf.addImage(pageData, 'JPEG', 左,上,宽度,高度)设置
pdf.addImage(pageData, 'JPEG', 20, 0, imgWidth, imgHeight)
pdf.save('hahah.pdf')// 下载

功能实现的具体使用

在我的代码中,我固定了dom容器的宽度为a4纸的宽,高度自适应,附带一个表格边框的样式,为什么要自己写表格样式、、、、因为坑啊

<div className="dom">
  <table className='pdftable'>.......</table>
</div>
.dom{
    
    
    width: 595.28px;
    margin:30px auto; /*no*/  
    background-color: white;
    position: relative;
}
//表格边框样式
.pdftable {
    
    
    width: 595.28px;
    border:1px solid #444; 
    border-top: none;
    border-spacing: 0;
}
.pdftable td{
    
    
    border-right: 1px solid #444;  
    border-bottom: 1px solid #444;
}
.pdftable tr td:last-child{
    
     border-right: 0 }
.pdftable tr:last-child td{
    
     border-bottom: 0 }

react中生成pdf的方法代码---------------------------------------------------------------------------------------------

const creatPdf= (htmlFlag, isOne) => {
    
    
    let htmls = Array.from(document.getElementsByClassName('pdftable'))
    console.log(htmls)
    let pageArr = []
    htmls.forEach(html => {
    
    
      let contentWidth = html.clientWidth // 获得该容器的宽
      let contentHeight = html.clientHeight // 获得该容器的高
      let canvas = document.createElement('canvas')
      let scale = 2  // 解决清晰度问题,先放大 2倍
      canvas.width = contentWidth * scale  // 将画布宽&&高放大两倍
      canvas.height = contentHeight * scale
      let content = canvas.getContext("2d")
      // content.scale(scale, scale) 如果canvas有偏移的话 可以考虑使用注释的这个来调动
      // let rect = html.getBoundingClientRect()
      // console.log(rect)
      // content.translate(0, -rect.y / scale)
      // content.translate(0, 10)
      let opts = {
    
    
        scale: scale,
        canvas: canvas,
        background: '#fff',
        width: contentWidth,
        height: contentHeight,
        useCORS: true,
        imageTimeout: 60000,
      }
      html2canvas(html, opts).then(canvas => {
    
    
        let pageData = canvas.toDataURL('image/jpeg', 1.0)
        pageArr.push({
    
     src: pageData, width: contentWidth, height: contentHeight })
        if (pageArr.length === htmls.length) {
    
    
          let pdf = new jsPDF('', 'pt', [595.28, pageArr[0].height])
          pageArr.forEach((page, index) => {
    
    
            console.log(page, index)
            if (index !== 0) {
    
    
              pdf.addPage()
            }
            //   a4纸的尺寸[595.28,841.89]
            let pdfHeight = page.height
            let pdfWidth = page.width
            if (page.height > 841.89) {
    
    
              pdfHeight = page.height // 841.89
              pdfWidth = 595.28
            }
            pdf.addImage(page.src, 'JPEG', 4, 8, pdfWidth - 16, pdfHeight - 16)
            // let pdf = new jsPDF('', 'pt', 'a4') // 下载尺寸 a4 纸 比例
            console.log(page.width, 'contentWidth')
            console.log(page.height, 'contentHeight')
            // pdf.addImage(pageData, 'JPEG', 左,上,宽度,高度)设置
          })
          setTimeout(() => {
    
    
            pdf.save(`test.pdf`)
          }, 100)
        }
      })
    })

上传后台的话还没有调通接口,暂时前端能使用的方法可以粘出来、、、

在截取页面表格,生成pdf后,转成后台需要的格式上传 (注意后台需要参数的数据类型 例如form…)

1.把pdf转成 blob格式

const blob= pdf.output("blob");
const formData = new FormData();
formData.append("file", pdf);
//formData 上传的请求参数

2.pdf先转base格式的字符串,再将base64格式的字符串转换为file文件

// 处理方法
const dataURLtoFile = (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});
};
let base64= pdf.output("datauristring");
let myfile = dataURLtoFile(base64, fileName);
let formData = new FormData();
formData.append('newFile', myfile);
//formData 上传的请求参数

3.另一种base64的方式

let datauri = pdf.output('dataurlstring')
let base64 = datauri.substring(28)
let formData = new FormData()
formData.append('newFile', base64)

在截取dom生成pdf时在网上找了很多的例子,看着都有道理但是一放在自己的代码中就又是另一种味道了,最后总算是磨出了一个适合自己代码中的方法。每个人的方法都有细微差异,还是要自己调试出满足自己的方法。 至于上传后台的方法,先找了几个方法,慢慢调、、、、、、

猜你喜欢

转载自blog.csdn.net/weixin_42508580/article/details/111475051