Vue前端如何实现生成PDF并下载功能详解

编辑: admin 分类: javascript 发布时间: 2021-11-17 来源:互联网
目录
  • 1. 安装及引入
  • 2. 封装导出 pdf 文件方法
    • 配置详解
    • 封装导出 pdf 文件方法(utils/htmlToPdf.js)
    • 相关组件中应用
    • 效果
    • 待优化部分
  • 总结

    思路: 通过 html2canvas 将 HTML 页面转换成图片,然后再通过 jspdf 将图片的 base64 生成为 pdf 文件。

    1. 安装及引入

    // 将页面 html 转换成图片
    npm install html2canvas --save  
    // 将图片生成 pdf
    npm install jspdf --save
    

    在项目主文件 main.js 中引入定义好的实现方法并注册

    import htmlToPdf from '@/utils/htmlToPdf';
    // 使用 Vue.use() 方法就会调用工具方法中的install方法
    Vue.use(htmlToPdf);
    

    传送门:Vue中 Vue.use() 原理及使用

    2. 封装导出 pdf 文件方法

    配置详解

    let pdf = new jsPDF('p', 'pt', [pdfX, pdfY]);
    第一个参数: l:横向  p:纵向
    第二个参数:测量单位("pt","mm", "cm", "m", "in" or "px");
    第三个参数:可以是下面格式,默认为“a4”。如需自定义格式,只需将大小作为数字数组传递,如:[592.28, 841.89];
    		   a0 - a10
    		   b0 - b10
    		   c0 - c10
      		   dl
    		   letter
    		   government-letter
    		   legal
    		   junior-legal
    		   ledger
    		   tabloid
    		   credit-card
    

    pdf.addPage()  在PDF文档中添加新页面,默认a4。参数如下:

    pdf.addImage()  将图像添加到PDF。参数如下:

    删除某页 pdf

    let targetPage = pdf.internal.getNumberOfPages(); //获取总页
    pdf.deletePage(targetPage); // 删除目标页
    

    保存 pdf 文档

    pdf.save(`测试.pdf`);
    

    封装导出 pdf 文件方法(utils/htmlToPdf.js)

    // 导出页面为PDF格式
    import html2Canvas from 'html2canvas'
    import JsPDF from 'jspdf'
    export default{
      install (Vue, options) {
        Vue.prototype.getPdf = function () {
          // 当下载pdf时,若不在页面顶部会造成PDF样式不对,所以先回到页面顶部再下载
          let top = document.getElementById('pdfDom');
          if (top != null) {
            top.scrollIntoView();
            top = null;
          }
          let title = this.exportPDFtitle;
          html2Canvas(document.querySelector('#pdfDom'), {
            allowTaint: true
          }).then(function (canvas) {
            // 获取canvas画布的宽高
            let contentWidth = canvas.width;
            let contentHeight = canvas.height;
    	      // 一页pdf显示html页面生成的canvas高度;
            let pageHeight = contentWidth / 841.89 * 592.28;
    	      // 未生成pdf的html页面高度
            let leftHeight = contentHeight;
    	      // 页面偏移
            let position = 0;
    	      // html页面生成的canvas在pdf中图片的宽高(本例为:横向a4纸[841.89,592.28],纵向需调换尺寸)
            let imgWidth = 841.89;
            let imgHeight = 841.89 / contentWidth * contentHeight;
            let pageData = canvas.toDataURL('image/jpeg', 1.0);
            let PDF = new JsPDF('l', 'pt', 'a4');
            // 两个高度需要区分: 一个是html页面的实际高度,和生成pdf的页面高度
            // 当内容未超过pdf一页显示的范围,无需分页
            if (leftHeight < pageHeight) {
              PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
            } else {
              while (leftHeight > 0) {
                PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
                leftHeight -= pageHeight;
                position -= 592.28;
                // 避免添加空白页
                if (leftHeight > 0) {
                  PDF.addPage();
                }
              }
            }
            PDF.save(title + '.pdf')
          })
        }
      }
    }
    

    相关组件中应用

    <template>
      <div class="wrap" >
        <div id="pdfDom" style="padding: 10px;">
          <el-table
            :data="tableData"
            border>
            <el-table-column prop="date" label="日期" width="250"></el-table-column>
            <el-table-column prop="name" label="姓名" width="250"></el-table-column>
            <el-table-column prop="address" label="地址"></el-table-column>
          </el-table>
        </div>
        <button type="button" style="margin-top: 20px;" @click="btnClick">导出PDF</button>
      </div>
    
    </template>
     
    <script>
    export default {
      data() { 
        return {
          exportPDFtitle: "页面导出PDF文件名",
          tableData: [
             {
              date: '2016-05-06',
              name: '王小虎',
              address: '重庆市九龙坡区火炬大道'
            },美国cn2服务器http://www.558idc.com/mg.html {
              date: '2016-05-07',
              name: '王小虎',
              address: '重庆市九龙坡区火炬大道'
            },{
              date: '2016-05-03',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄'
            }, {
              date: '2016-05-02',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄'
            }, {
              date: '2016-05-04',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄'
            }, {
              date: '2016-05-01',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄'
            }, {
              date: '2016-05-08',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄'
            }, {
              date: '2016-05-06',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄'
            }, {
              date: '2016-05-06',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄'
            }, {
              date: '2016-05-07',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄'
            }, {
              date: '2016-05-01',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄'
            }, {
              date: '2016-05-08',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄'
            }, {
              date: '2016-05-06',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄'
            }, {
              date: '2016-05-07',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄'
            }, {
              date: '2016-05-06',
              name: '王小虎',
              address: '南京市江宁区将军大道'
            }, {
              date: '2016-05-07',
              name: '王小虎',
              address: '南京市江宁区将军大道'
            },, {
              date: '2016-05-04',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄'
            }, {
              date: '2016-05-01',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄'
            }, {
              date: '2016-05-08',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄'
            }, {
              date: '2016-05-06',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄'
            }, {
              date: '2016-05-07',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄'
            },{
              date: '2016-05-01',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄'
            }, {
              date: '2016-05-08',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄'
            }, {
              date: '2016-05-06',
              name: '王小虎',
              address: '上海市普陀区金沙江路 1518 弄'
            }, {
              date: '2016-05-08',
              name: '王小虎',
              address: '武汉市洪山区文化大道'
            }, {
              date: '2016-05-06',
              name: '王小虎',
              address: '武汉市洪山区文化大道'
            }, {
              date: '2016-05-07',
              name: '王小虎',
              address: '武汉市洪山区文化大道'
            }, {
              date: '2016-05-06',
              name: '王小虎',
              address: '南京市江宁区将军大道'
            }, {
              date: '2016-05-07',
              name: '王小虎',
              address: '武汉市洪山区文化大道'
            },
          ]
        } 
      }, 
      methods: {
        btnClick(){
          this.$nextTick(() => {this.getPdf();})
        },
      },  
    }
    </script>  
    

    效果

    待优化部分

    1. 分页时,页面内容被截断(欢迎留言讨论交流);
    2. 不同内容,另起一页开始;思路:计算超出内容,占最后一页的高度(设定间距 =  页面高度 - 超出部分高度)。

    总结

    到此这篇关于Vue前端如何实现生成PDF并下载功能的文章就介绍到这了,更多相关Vue前端生成PDF并下载内容请搜索hwidc以前的文章或继续浏览下面的相关文章希望大家以后多多支持hwidc!