1.首先在文件内引入htmlToPdf.js
这里代码引入了html2canvas和jspdf
//需要 npm i html2Canvas 和 npm i jspdf
在这里将getPdf 这个函数挂载到Vue的原型上,最后return一个promise对象(包含了resolve的base64Pdf,以便于处理),在局部组件内可进行.then以进行上传后端等操作。
插件代码如下
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
export default {
install(Vue, options) {
/**
*
* @param {*} reportName 下载时候的标题
* @param {*} isDownload 是否下载默认为下载,传false不下载
*/
Vue.prototype.getPdf = function (reportName, isDownload = true) {
// 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')
}
// 删除本地存储的base64字段
var pdfData = PDF.output('datauristring')//获取base64Pdf
resolve(pdfData)
}
)
})
}
}
}
import htmlToPdf from '@/utils/htmlToPdf.js'
Vue.use(htmlToPdf)
<div
style="
height: 69vh;
overflow-y: auto;
font-size: 16px;
padding: 10px 10px;
">
<div id="pdfDom">//为需要导出的DOM添加id
<div v-for="(item,index) in dataText2" :key="index" >
<div
style="white-space: pre-wrap; width: 100%; height: 100%"
v-html="item"
>
</div>
</div>
</div>
</div>
<el-button
type="success"
@click="toGetPdf()"//触发事件
style="width: 150px; background: #409eff;margin-left:100px"
>
导出内容为PDF
</el-button>
//如果不需要上传直接导出到这一步就可以了,只需要将download = true即可导出
toGetPdf(tile = "", download = false) {
this.getPdf(tile, download) //download:false为不下载,这里调用了刚刚引用的全局函数,.then得到的值是base64位的pdf文件
.then((res) => {
this.UploadPdf(res);
});
},
//如果需要上传到后台
UploadPdf(res) {
//res拿到base64的pdf
let pdfBase64Str = res;
let title = "上传给后端的个人报告";
var myfile = this.dataURLtoFile(pdfBase64Str, title + ".pdf"); //调用一下下面的转文件流函数
//let fd = new FormData(); ///忽略这边的我个人的上传请求,我这边是将jspdf生成的单层PDF,交给后台变为双层的
//fd.append("files", myfile);
//fd.append("serverFilePath", path);
//this.$http({
//url:
//window.SITE_CONFIG["orcUrl1"] +
//"/rest/file/small/nr/upload/files_pdf",
// method: "post",
// data: fd,
// rest: true,
// isFormData: true,
}).then((res) => {//这边是后台返回了base64的格式,所以我要转为blob
const blob = this.base64ToBlob(res.data);
const elink = document.createElement("a");
// const fname = item.name + str + "_" + lists[1] + lists[2]; // 下载文件的名字
const fname = "pdf"; // 下载文件的名字
elink.download = fname;
elink.style.display = "none";
elink.href = URL.createObjectURL(blob);
document.body.appendChild(elink);
elink.click();
URL.revokeObjectURL(elink.href); // 释放URL 对象
document.body.removeChild(elink);
// if (window.navigator && window.navigator.msSaveOrOpenBlob) {//这个是跳转新窗口直接打开
// window.navigator.msSaveOrOpenBlob(blob);
// } else {
// const fileURL = URL.createObjectURL(blob);
// window.open(fileURL);
// }
});
},
base64ToBlob(code) {//base64转二进制流(blob)
code = code.replace(/[\n\r]/g, "");
const raw = window.atob(code);
const rawLength = raw.length;
const uInt8Array = new Uint8Array(rawLength);
for (let i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}
return new Blob([uInt8Array], { type: "application/pdf" });
},
/*
将base64转换为文件,接收2个参数,第一是base64,第二个是文件名字
最后返回文件对象
*/
dataURLtoFile(dataurl, filename) {
var arr = dataurl.split(","),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], filename, { type: mime });
},
vue导出pdf以及过程中滚动条内容无法获取的问题,可视区外的读取不了,导致生成的PDF不全
在导出时,有时候会出现导出内容有滚动条的话导出内容不全,只能导出可视部分,滚动条隐藏掉的内容不会展示出来,这个问题我也看了很多的文档,发现都没有什么好的方法可以解决,所以我的解决方法就是:把含有滚动条的内容放在页面外部,
<div
style="
height: 69vh;
overflow-y: auto;
font-size: 16px;
padding: 10px 10px;
">
<div id="pdfDom">//将id放在被读取的内容外面,
// 简单来说就是用pdfDom把出现滚动条的内容包裹起来
<div v-for="(item,index) in dataText2" :key="index" >
<div
style="white-space: pre-wrap; width: 100%; height: 100%"
v-html="item"
>
</div>
</div>
</div>
</div>
打印实现
//打印功能,dataResult是后台返回的base64
let blob = this.dataURLtoBlob(dataResult);
var date = (new Date()).getTime()
var ifr = document.createElement('iframe')
ifr.style.frameborder = 'no'
ifr.style.display = 'none'
ifr.style.pageBreakBefore = 'always'
ifr.setAttribute('id', 'printPdf' + date)
ifr.setAttribute('name', 'printPdf' + date)
ifr.src = window.URL.createObjectURL(blob)
document.body.appendChild(ifr)
this.doPrint('printPdf' + date)
window.URL.revokeObjectURL(ifr.src) // 释放URL 对象