前端将表格页面导出为 PDF 并适配 A4纸张的思路

文章目录


最终效果

这个是原页面

这个是前端处理成 pdf 的效果


技术依赖包

vue2 + element + html2canvas + jsPDF

html2Canvas 官网
jsPDF 官网


优缺点

  • 优点:就是不需要后端处理 pdf 了,原本想着把 domcss 传递给后端让后端生成,奈何后端是 php,解析器不给力(这是后端跟我讲的,有没有懂 php 大佬)
  • 缺点:生成的 pdf 比较糊,而且表格在分页的时候容易分裂,我暂时没有更好的方案

实现思路

  • html 先转换成 canvas ,然后生成图片,最后再将图片转换成 pdf
  • 需要先把页面适配一下 A4 纸张大小,不然下面切割的话会出问题

代码

javascript 复制代码
import html2canvas from 'html2canvas'
import { jsPDF } from 'jspdf'

async handleUploadHTMLPDF() {
  try {
        this.loading.print = true
        const dom: any = document.querySelector('#printContent')
        const query = this.$route.query
        const id = query?.id
        if (dom) {
            html2canvas(dom).then(async canvas => {
                let pdf = new jsPDF('p', 'mm', 'a4') // A4纸,纵向
                let ctx: any = 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: any = 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() // 如果后面还有内容,添加一个空页
                    }
                    // delete page;
                }
                // 保存文件
                pdf.save('output.pdf')
                const blob = pdf.output('blob')
                const base64 = await this.blobToBase64(blob)
                // 之后想传给后端 blob 或者 base64 随便你
            })
        }
    } catch (err) {
        console.log(err)
    }
}
blobToBase64 = (blob: Blob): Promise<string> => {
    return new Promise(resolve => {
        const reader = new FileReader()
        reader.onloadend = () => resolve(reader.result as string)
        reader.readAsDataURL(blob)
    })
}

相关推荐
小雨下雨的雨10 分钟前
基于鸿蒙PC Electron框架技术完成的表单验证技术详解
前端·javascript·华为·electron·前端框架·鸿蒙
提子拌饭13312 分钟前
饮料含糖量查询应用 - 鸿蒙PC用Electron框架完整实现
前端·javascript·华为·electron·前端框架·鸿蒙
JustHappy13 分钟前
古法编程秘籍(五):什么是进程和线程?从软件到 CPU 的一次完整旅程
前端·后端·代码规范
HappyAcmen14 分钟前
2.PDF长文档完整读取
python·pdf·rag
慈云数据18 分钟前
【免费开源】多格式文件转换工具 Pro:图片、PDF、文档、批量重命名一站式转换
pdf
爱编程的小金20 分钟前
前端请求库的下一个进化方向:从 Promise 到策略化
前端·alova·前端请求库·请求策略
hsg7721 分钟前
简述:Jensen Huang‘s Footsteps网站全内容分析
前端·javascript·数据库
珑墨1 小时前
前端 AI 开发通用skill
前端
kyriewen1 小时前
一个人+Cursor,7天上线付费小程序:第1天我就想放弃了
前端·微信小程序·cursor
大家的林语冰1 小时前
Angular 王者归来,第 22 个主版本亮相,一大波前沿技术再度引领潮流!
前端·javascript·前端框架