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

目录
  • 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: '重庆市九龙坡区火炬大道'
        }, {
          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并下载内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Vue导出页面为PDF格式的实现思路

    通过网上的查阅以后,说一下思路.就是将页面转换成图片格式.然后通过图片的base64码.生成PDF..看了他们的文章,做了如下整理.. 说起来很容易,那么具体怎么实现呢? 1 .我们要添加两个模块 第一个.将页面html转换成图片 npm install --save html2canvas 第二个.将图片生成pdf npm install jspdf --save 2.定义全局函数..创建一个htmlToPdf.js文件在指定位置.我个人习惯放在('src/components/utils/h

  • vue实现pdf导出解决生成canvas模糊等问题(推荐)

    最近公司项目需要,利用vue实现pdf导出,从而保存到本地打印出来,说起来好像也很容易,具体要怎么实现呢? 1  .我们要添加两个模块 1 第一个.将页面html转换成图片 2 npm install --save html2canvas 3 第二个.将图片生成pdf 4 npm install jspdf --save 2 .定义全局函数 .. 创建一个htmlToPdf .js 文件在指定位置 . 我个人习惯放在 ( ' src /utils/htmlToPdf' ) // 导出页面为PDF

  • vue实现在线预览pdf文件和下载(pdf.js)

    最近做项目遇到在线预览和下载pdf文件,试了多种pdf插件,例如jquery.media.js(ie无法直接浏览) 最后选择了pdf.js插件(兼容ie10及以上.谷歌.安卓,苹果) 强烈推荐改插件,以下介绍用法 (1)下载插件 下载路径: pdf.js (2)将下载构建后的插件放到文件中public(vue/cli 3.0) (3)在vue文件中直接使用,贴上完整代码 <template> <div class="wrap"> <iframe :src=

  • vue实现pdf文档在线预览功能

    针对android系统不支持pdf文档在线预览,可通过引入pdf.js插件实现,其具体实现步骤如下 一.引入插件 方式一:npm install --save pdfjs-dist,安装完成后在vue项目的node_modules出现如下依赖 方式二:只引入pdf.js的核心文件pdf.js和pdf.work.js,其他无关的文件全部删除,如图 方式三:将插件直接放在static文件夹下,如图 二.前端页面代码 方式一和方式二:特点精简 <template> <div> <c

  • vue中将网页打印成pdf实例代码

    整理文档,搜刮出一个vue中将网页打印成pdf的代码,稍微整理精简一下做下分享. <template> <div class="pdf-wrap" id="pdfWrap"> <button v-on:click="getPdf">点击下载PDF</button> <div class="pdf-dom" id="pdfDom"></div&

  • Vue如何将页面导出成PDF文件

    本文实例为大家分享了Vue将页面导出成PDF文件的具体代码,供大家参考,具体内容如下 我在前端岗位上要实现个可视化图表页的PDF文件导出,在这里给大家分享下使用jsPDF和html2canvas包将Vue页面导出成PDF的方法. 1. 下载npm包 npm install html2canvas npm install jspdf 2. 创建插件.js文件 Vue-cli项目的话是在./utils文件夹下,我在这里使用的nuxt框架,所以是在./plugins文件夹下. import html2

  • Vue将页面导出为图片或者PDF

    本文实例为大家分享了Vue导出页面为PDF格式的具体代码,供大家参考,具体内容如下 导出为图片 1.将页面html转换成图片 npm install html2canvas --save 2.在需要导出的页面引入 import html2canvas from 'html2canvas'; 在 methods 中添加方法 dataURLToBlob(dataurl) {//ie 图片转格式 var arr = dataurl.split(','), mime = arr[0].match(/:(

  • vue中如何实现pdf文件预览的方法

    今天产品提出一个优化的需求,就是之前我们做的图片展示就是一个img标签搞定,由于我们做的是海外后台管理系统,那边的人上传的文件时pdf格式,vue本事是不支持这种格式文件展示的,于是就google搜索,发现有iframe.embed.vueshowpdf(测试了不咋好用).pdf等,本文说一下pdf插件的使用过程. 说明:iframe标签这种,对于有的链接是可以的,比如这种链接在服务器端没有设置享有头content-disposition,就可以直接显示,如下: 想复制代码如下: <iframe

  • vue2.0全局组件之pdf详解

    目的:像elementUI那样注册全局组件 预览pdf文件 技术支持:使用火狐的pdf.js http://mozilla.github.io/pdf.js/ 准备:新建一个CPdf.vue文件,把火狐demo里面的build里面的pdf.js下载来,并且依赖了elementUI开发的其实就是用了<el-button> 编写: template <template> <div class="cpdf"> <div class="cen

  • vue中使用vue-pdf的方法详解

    需求:简单说~~有两个pdf文件需在h5上展示,通过点击按钮切换不同文件的显示 注: 1.vue-pdf默认展示首页,我这里的需求是通过滑动展示所有页面,这里使用的v-for遍历.有多少页就加载了多少个pdf组件. 2.pdf文件存在跨域问题,这个需要后端同学支持. 3.demo上的pdf文件只有一页,测试多页展示,自己改用多页pdf文件即可 <template> <div class="pdf_wrap"> <div class="pdf_li

随机推荐