首页 > 其他分享 >VUE html2canvas+jsPdf 下载PDF文件并且以文件流的形式传给后端 + 分页处理截断文字问题

VUE html2canvas+jsPdf 下载PDF文件并且以文件流的形式传给后端 + 分页处理截断文字问题

时间:2022-12-22 17:01:57浏览次数:44  
标签:jsPdf 文件 canvas VUE pageHeight let var pdf document

安装:

npm install html2canvas --save

npm install jsPDF --save

配置:

 

 

//转化PDF组件 import htmlToPdf from '@/utils/contract/htmlToPdf' Vue.use(htmlToPdf)  

新建:

import html2Canvas from 'html2canvas' import JsPDF from 'jspdf' export default {   install(Vue, options) {     /**      *      * @param {*} reportName 下载时候的标题      * @param {*} isDownload  是否下载默认为下载,传false不下载      */     Vue.prototype.getPdf = function (reportName, isDownload) {       //     var target = document.getElementsByClassName("right-aside")[0];       // target.style.background = "#FFFFFF";       return new Promise((resolve, reject) => {         var title = reportName;         html2Canvas(document.querySelector('#pdfDom'), {           allowTaint: true         }).then((canvas) => {           let contentWidth = canvas.width           let contentHeight = canvas.height           //一页pdf显示html页面生成的canvas高度;           let pageHeight = contentWidth / 592.28 * 841.89           //未生成pdf的html页面高度           let leftHeight = contentHeight           //页面偏移           let position = 0           //a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高           let imgWidth = 595.28           let imgHeight = 592.28 / contentWidth * contentHeight           let pageData = canvas.toDataURL('image/jpeg', 1.0)           let PDF = new JsPDF('', 'pt', 'a4')           //有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)           //当内容未超过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 -= 841.89               //避免添加空白页               if (leftHeight > 0) {                 PDF.addPage() //`在这里插入代码片`               }             }           }           if (isDownload) {             PDF.save(title + '.pdf')           } else {             // 删除本地存储的base64字段             var pdfData = PDF.output('datauristring')//获取base64Pdf             //利用promise 回调到页面中去             resolve(pdfData)           }         }         )       })     }   } }

页面:

解题:获取所有的需要下载的外层盒子,循环处理这些盒子,获取当前盒子距离顶部的高度offsetTop加上盒子的高度是否大于a4纸的高度,如果大于就在之前插入空白盒子,把内容挤下去

dom结构(需要在下载区域的所有外层盒子添加类似于item这样的类名)

<div class="content" id="content">
    <div class="item">内容</div>
    <div class="item">内容</div>
    <!--    每一块dom的class类设置成item(自定义)以此处理内容分割  -->
    <div class="item">内容</div>
    <div class="item">内容</div>
</div>

//避免分页被截断
outPutPdfFn () {
let vm = this;
const A4_WIDTH = 592.28;
const A4_HEIGHT = 841.89;
// $myLoading 自定义等待动画组件,实现导出事件的异步等待交互
vm.$nextTick(() => {
// dom的id。
let target = document.getElementById('upload');
let pageHeight = target.scrollWidth / A4_WIDTH * A4_HEIGHT;
// 获取分割dom,此处为class类名为item的dom
let lableListID = document.getElementsByClassName('item');
// 进行分割操作,当dom内容已超出a4的高度,则将该dom前插入一个空dom,把他挤下去,分割
for (let i = 0; i < lableListID.length; i++) {
let multiple = Math.ceil((lableListID[i].offsetTop + lableListID[i].offsetHeight) / pageHeight);
if (this.isSplit(lableListID, i, multiple * pageHeight)) {
let divParent = lableListID[i].parentNode; // 获取该div的父节点
let newNode = document.createElement('div');
newNode.className = 'emptyDiv';
newNode.style.background = '#01195e';
let _H = multiple * pageHeight - (lableListID[i].offsetTop + lableListID[i].offsetHeight);
newNode.style.height = _H + 30 + 'px';
newNode.style.width = '100%';
let next = lableListID[i].nextSibling; // 获取div的下一个兄弟节点
// 判断兄弟节点是否存在
console.log(next);
if (next) {
// 存在则将新节点插入到div的下一个兄弟节点之前,即div之后
divParent.insertBefore(newNode, next);
} else {
// 不存在则直接添加到最后,appendChild默认添加到divParent的最后
divParent.appendChild(newNode);
}
}
}
this.pdf();
});
},
// 判断是否需要添加空白div
isSplit (nodes, index, pageHeight) {
// 计算当前这块dom是否跨越了a4大小,以此分割
if (nodes[index].offsetTop + nodes[index].offsetHeight < pageHeight && nodes[index + 1] && nodes[index + 1].offsetTop + nodes[index + 1].offsetHeight > pageHeight) {
return true;
}
return false;
},
pdf() {
// 避免出现浏览器滚动条导致的内容不全处理
document.body.scrollTop = 0;
//div内部滚动导致内容不全处理
document.getElementById("app").style.height = 'auto';
setTimeout(()=>{
html2canvas(document.getElementById("upload"), {
background: '#01195e',
allowTaint : true,
// height: document.getElementById('upload').scrollHeight,
// windowHeight: document.getElementById('upload').scrollHeight
}).then(canvas => {
var contentWidth = canvas.width;
var contentHeight = canvas.height;

//一页pdf显示html页面生成的canvas高度;
var pageHeight = contentWidth / 592.28 * 841.89;
//未生成pdf的html页面高度
var leftHeight = contentHeight;
//页面偏移
var position = 0;
//a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
var imgWidth = 595.28;
var imgHeight = 592.28 / contentWidth * contentHeight;

var pageData = canvas.toDataURL('image/jpeg', 1.0);

var pdf = new jsPDF('', 'pt', 'a4');

//有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
//当内容未超过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 -= 841.89;
//避免添加空白页
if (leftHeight > 0) {
pdf.addPage();
}
}
}
pdf.save("content.pdf");
document.getElementById("app").style.height = '100%';
document.getElementsByClassName("emptyDiv")[0].parentNode.removeChild(document.getElementsByClassName("emptyDiv")[0]);
})

},300)

},

 

标签:jsPdf,文件,canvas,VUE,pageHeight,let,var,pdf,document
From: https://www.cnblogs.com/shenbo666/p/16999118.html

相关文章

  • eclipse资源管理器直接打开文件目录方法
    eclipse资源管理器直接打开文件目录方法:运行→外部工具→外部工具配置→程序(点击左上角有个文本+号的图标)→在名称输入“资源管理器”位置输入“C:\Windows\explorer.exe”......
  • Linux文件系统
    管理文件系统使用Linux系统时,需要作出的决策之一就是为存储设备选用什么文件系统。大多数Linux发行版在安装时会非常贴心地提供默认的文件系统,大多数入门级用户想都不......
  • 理解 Linux 文件权限
    理解Linux文件权限缺乏安全性的系统不是完整的系统。系统中必须有一套能够保护文件免遭非授权用户浏览或修改的机制。Linux沿用了Unix文件权限的办法,即允许用户和组......
  • vue插槽使用
    插槽的分类插槽分为默认插槽、具名插槽、作用域插槽需要注意的点是,使用作用域插槽需要搭配template使用默认插槽默认插槽使用最为简单:父级<template><div>......
  • 文件处理
    文件打开open()函数两个参数:文件名以及打开模式file路径有‘\’路径前加r-"r"-读取-默认值。打开文件进行读取,如果文件不存在则报错。默认-"a"-追加-......
  • VUE3状态管理Pinia使用介绍
    vue3中推荐使用的状态管理工具:pinia,真的很好用官方文档,中文文档一、安装piniayarnaddpinia#或者使用npmnpminstallpinia二、src文件夹下新建store文件夹,并新建......
  • linux下制作ext4文件系统
    1.生成一个空的2MiB文件ddif=/dev/zeroof=rootfs.ext4bs=1024count=2048(指定每一块大小为1024字节,一共又2048块,那么就是2048*1024B=2MiB)2.对生成的文件......
  • Vite + Vue 3 + electron 环境搭建
    第1步,建立一个新的vite项目yarncreatevite第2步,安装项目依赖yarnadd-Dconcurrentlycross-envelectronelectron-builderwait-on第3部,修改package.json......
  • SpringMVC实现文件上传
    1、在springmvc.xml中配置文件解析器<!--配置文件解析器对象,要求id名称必须是multipartResolver--><beanid="multipartResolver"class="org.springframework.web......
  • Vue、angular等框架实现双向绑定的原理,核心机制是使用了Object.defineProperty
    <divid="name"></div>varobj={};Object.defineProperty(obj,"name",{set:newVal=>(document.querySelector("#name").innerHTML=newVal)});obj.name="修改后,内......