Vue中 前端实现生成 PDF 并下载

简介: Vue中 前端实现生成 PDF 并下载

思路: 通过 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。参数如下:

2020062310470442.png

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

2020062310470442.png

删除某页 pdf

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

保存 pdf 文档

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

2020062310470442.png

封装导出 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: '重庆市九龙坡区火炬大道'
        }, {
          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>  

效果

2020062310470442.png

待优化部分

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


相关文章
|
JavaScript 前端开发 Java
制造业ERP源码,工厂ERP管理系统,前端框架:Vue,后端框架:SpringBoot
这是一套基于SpringBoot+Vue技术栈开发的ERP企业管理系统,采用Java语言与vscode工具。系统涵盖采购/销售、出入库、生产、品质管理等功能,整合客户与供应商数据,支持在线协同和业务全流程管控。同时提供主数据管理、权限控制、工作流审批、报表自定义及打印、在线报表开发和自定义表单功能,助力企业实现高效自动化管理,并通过UniAPP实现移动端支持,满足多场景应用需求。
1241 1
|
移动开发 前端开发 JavaScript
Vue与React两大前端框架的主要差异点
以上就是Vue和React的主要差异点,希望对你有所帮助。在选择使用哪一个框架时,需要根据项目的具体需求和团队的技术栈来决定。
740 83
|
人工智能 文字识别 自然语言处理
熊猫 OCR 识别软件下载,支持截图 OCR、PDF 识别、多语言翻译的免费全能工具,熊猫OCR识别
本文介绍了几款实用的图文识别软件,包括熊猫OCR、Umi-OCR和天若OCR_本地版。熊猫OCR功能强大,支持多窗口操作、AI找图找色、OCR识别等;Umi-OCR免费且高效,具备截图OCR、批量处理等功能;天若OCR界面简洁,适合快速文字识别。文章还提供了下载链接及软件特点、界面展示等内容,便于用户根据需求选择合适的工具。
1497 36
|
JavaScript 前端开发 编译器
Vue与TypeScript:如何实现更强大的前端开发
Vue.js 以其简洁的语法和灵活的架构在前端开发中广受欢迎,而 TypeScript 作为一种静态类型语言,为 JavaScript 提供了强大的类型系统和编译时检查。将 Vue.js 与 TypeScript 结合使用,不仅可以提升代码的可维护性和可扩展性,还能减少运行时错误,提高开发效率。本文将介绍如何在 Vue.js 项目中使用 TypeScript,并通过一些代码示例展示其强大功能。
529 22
|
存储 安全 算法
Java 集合面试题 PDF 下载及高频考点解析
本文围绕Java集合面试题展开,详细解析了集合框架的基本概念、常见集合类的特点与应用场景。内容涵盖`ArrayList`与`LinkedList`的区别、`HashSet`与`TreeSet`的对比、`HashMap`与`ConcurrentHashMap`的线程安全性分析等。通过技术方案与应用实例,帮助读者深入理解集合类的特性和使用场景,提升解决实际开发问题的能力。文末附带资源链接,供进一步学习参考。
326 4
|
人工智能 JavaScript 前端开发
Vue 性能革命:揭秘前端优化的终极技巧;Vue优化技巧,解决Vue项目卡顿问题
Vue在处理少量数据和有限dom的情况下技术已经非常成熟了,但现在随着AI时代的到来,海量数据场景会越来越多,Vue优化技巧也是必备技能。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
JavaScript 前端开发 UED
PDF在线预览实现:如何使用vue-pdf-embed实现前端PDF在线阅读
本文详细介绍了如何在Vue项目中使用vue-pdf-embed实现PDF文件的在线展示。从项目初始化、插件集成到高级功能的实现和部署优化,希望对你有所帮助。在实际项目中,灵活运用这些技术可以大大提升用户体验和项目质量。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
数据采集 前端开发 JavaScript
PDF预览:利用vue3-pdf-app实现前端PDF在线展示
通过本文的介绍,我们详细了解了如何在Vue3项目中使用vue3-pdf-app实现PDF文件的在线展示。从项目初始化、插件集成到高级功能的实现和部署优化,希望对你有所帮助。在实际项目中,灵活运用这些技术可以大大提升用户体验和项目质量。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
存储 人工智能 前端开发
前端大模型应用笔记(三):Vue3+Antdv+transformers+本地模型实现浏览器端侧增强搜索
本文介绍了一个纯前端实现的增强列表搜索应用,通过使用Transformer模型,实现了更智能的搜索功能,如使用“番茄”可以搜索到“西红柿”。项目基于Vue3和Ant Design Vue,使用了Xenova的bge-base-zh-v1.5模型。文章详细介绍了从环境搭建、数据准备到具体实现的全过程,并展示了实际效果和待改进点。
1626 14
|
JavaScript 前端开发 程序员
前端学习笔记——node.js
前端学习笔记——node.js
1042 0

热门文章

最新文章