经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » Vue.js » 查看文章
Vue前端如何实现生成PDF并下载功能详解
来源:jb51  时间:2021/10/8 11:07:29  对本文有异议

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

1. 安装及引入

  1. // 将页面 html 转换成图片
  2. npm install html2canvas --save
  3. // 将图片生成 pdf
  4. npm install jspdf --save

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

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

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

2. 封装导出 pdf 文件方法

配置详解

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

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

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

删除某页 pdf

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

保存 pdf 文档

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

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

  1. // 导出页面为PDF格式
  2. import html2Canvas from 'html2canvas'
  3. import JsPDF from 'jspdf'
  4. export default{
  5. install (Vue, options) {
  6. Vue.prototype.getPdf = function () {
  7. // 当下载pdf时,若不在页面顶部会造成PDF样式不对,所以先回到页面顶部再下载
  8. let top = document.getElementById('pdfDom');
  9. if (top != null) {
  10. top.scrollIntoView();
  11. top = null;
  12. }
  13. let title = this.exportPDFtitle;
  14. html2Canvas(document.querySelector('#pdfDom'), {
  15. allowTaint: true
  16. }).then(function (canvas) {
  17. // 获取canvas画布的宽高
  18. let contentWidth = canvas.width;
  19. let contentHeight = canvas.height;
  20. // 一页pdf显示html页面生成的canvas高度;
  21. let pageHeight = contentWidth / 841.89 * 592.28;
  22. // 未生成pdf的html页面高度
  23. let leftHeight = contentHeight;
  24. // 页面偏移
  25. let position = 0;
  26. // html页面生成的canvas在pdf中图片的宽高(本例为:横向a4纸[841.89,592.28],纵向需调换尺寸)
  27. let imgWidth = 841.89;
  28. let imgHeight = 841.89 / contentWidth * contentHeight;
  29. let pageData = canvas.toDataURL('image/jpeg', 1.0);
  30. let PDF = new JsPDF('l', 'pt', 'a4');
  31. // 两个高度需要区分: 一个是html页面的实际高度,和生成pdf的页面高度
  32. // 当内容未超过pdf一页显示的范围,无需分页
  33. if (leftHeight < pageHeight) {
  34. PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
  35. } else {
  36. while (leftHeight > 0) {
  37. PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
  38. leftHeight -= pageHeight;
  39. position -= 592.28;
  40. // 避免添加空白页
  41. if (leftHeight > 0) {
  42. PDF.addPage();
  43. }
  44. }
  45. }
  46. PDF.save(title + '.pdf')
  47. })
  48. }
  49. }
  50. }

相关组件中应用

  1. <template>
  2. <div class="wrap" >
  3. <div id="pdfDom" style="padding: 10px;">
  4. <el-table
  5. :data="tableData"
  6. border>
  7. <el-table-column prop="date" label="日期" width="250"></el-table-column>
  8. <el-table-column prop="name" label="姓名" width="250"></el-table-column>
  9. <el-table-column prop="address" label="地址"></el-table-column>
  10. </el-table>
  11. </div>
  12. <button type="button" style="margin-top: 20px;" @click="btnClick">导出PDF</button>
  13. </div>
  14.  
  15. </template>
  16. <script>
  17. export default {
  18. data() {
  19. return {
  20. exportPDFtitle: "页面导出PDF文件名",
  21. tableData: [
  22. {
  23. date: '2016-05-06',
  24. name: '王小虎',
  25. address: '重庆市九龙坡区火炬大道'
  26. }, {
  27. date: '2016-05-07',
  28. name: '王小虎',
  29. address: '重庆市九龙坡区火炬大道'
  30. },{
  31. date: '2016-05-03',
  32. name: '王小虎',
  33. address: '上海市普陀区金沙江路 1518 弄'
  34. }, {
  35. date: '2016-05-02',
  36. name: '王小虎',
  37. address: '上海市普陀区金沙江路 1518 弄'
  38. }, {
  39. date: '2016-05-04',
  40. name: '王小虎',
  41. address: '上海市普陀区金沙江路 1518 弄'
  42. }, {
  43. date: '2016-05-01',
  44. name: '王小虎',
  45. address: '上海市普陀区金沙江路 1518 弄'
  46. }, {
  47. date: '2016-05-08',
  48. name: '王小虎',
  49. address: '上海市普陀区金沙江路 1518 弄'
  50. }, {
  51. date: '2016-05-06',
  52. name: '王小虎',
  53. address: '上海市普陀区金沙江路 1518 弄'
  54. }, {
  55. date: '2016-05-06',
  56. name: '王小虎',
  57. address: '上海市普陀区金沙江路 1518 弄'
  58. }, {
  59. date: '2016-05-07',
  60. name: '王小虎',
  61. address: '上海市普陀区金沙江路 1518 弄'
  62. }, {
  63. date: '2016-05-01',
  64. name: '王小虎',
  65. address: '上海市普陀区金沙江路 1518 弄'
  66. }, {
  67. date: '2016-05-08',
  68. name: '王小虎',
  69. address: '上海市普陀区金沙江路 1518 弄'
  70. }, {
  71. date: '2016-05-06',
  72. name: '王小虎',
  73. address: '上海市普陀区金沙江路 1518 弄'
  74. }, {
  75. date: '2016-05-07',
  76. name: '王小虎',
  77. address: '上海市普陀区金沙江路 1518 弄'
  78. }, {
  79. date: '2016-05-06',
  80. name: '王小虎',
  81. address: '南京市江宁区将军大道'
  82. }, {
  83. date: '2016-05-07',
  84. name: '王小虎',
  85. address: '南京市江宁区将军大道'
  86. },, {
  87. date: '2016-05-04',
  88. name: '王小虎',
  89. address: '上海市普陀区金沙江路 1518 弄'
  90. }, {
  91. date: '2016-05-01',
  92. name: '王小虎',
  93. address: '上海市普陀区金沙江路 1518 弄'
  94. }, {
  95. date: '2016-05-08',
  96. name: '王小虎',
  97. address: '上海市普陀区金沙江路 1518 弄'
  98. }, {
  99. date: '2016-05-06',
  100. name: '王小虎',
  101. address: '上海市普陀区金沙江路 1518 弄'
  102. }, {
  103. date: '2016-05-07',
  104. name: '王小虎',
  105. address: '上海市普陀区金沙江路 1518 弄'
  106. },{
  107. date: '2016-05-01',
  108. name: '王小虎',
  109. address: '上海市普陀区金沙江路 1518 弄'
  110. }, {
  111. date: '2016-05-08',
  112. name: '王小虎',
  113. address: '上海市普陀区金沙江路 1518 弄'
  114. }, {
  115. date: '2016-05-06',
  116. name: '王小虎',
  117. address: '上海市普陀区金沙江路 1518 弄'
  118. }, {
  119. date: '2016-05-08',
  120. name: '王小虎',
  121. address: '武汉市洪山区文化大道'
  122. }, {
  123. date: '2016-05-06',
  124. name: '王小虎',
  125. address: '武汉市洪山区文化大道'
  126. }, {
  127. date: '2016-05-07',
  128. name: '王小虎',
  129. address: '武汉市洪山区文化大道'
  130. }, {
  131. date: '2016-05-06',
  132. name: '王小虎',
  133. address: '南京市江宁区将军大道'
  134. }, {
  135. date: '2016-05-07',
  136. name: '王小虎',
  137. address: '武汉市洪山区文化大道'
  138. },
  139. ]
  140. }
  141. },
  142. methods: {
  143. btnClick(){
  144. this.$nextTick(() => {this.getPdf();})
  145. },
  146. },
  147. }
  148. </script>

效果

待优化部分

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

总结

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

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号