vue使用html2canvas结合jsPDF实现前端页面转pdf功能,支持分页

简单的记录一下再vue中使用html2canvas结合jsPDF实现对页面转pdf功能的实现,主要是通过html2canvas将页面转化为高清的图片,后在进行导出pdf,话不多说,直接上代码

注意:如果使用的是uniapp的话,需要将div替换成view,以下代码可直接使用

第一步:通过npm安装html2canvas和jsPDF

npm install --save htmlcanvas2
npm install --save jspdf

第二步:则是在需要的页面引入后,通过$refs获取需要转成pdf容器的dom元素 ,通过html2canvas将页面转化为高清图片后在通过jsPDF导出为pdf文件(以下代码复制可直接使用)

<template>
	<div>
		<div @click="print" class="btn">转PDF</div>
		<div ref="box" class="box">
			<div class="item" v-for="item in data">{
   
   {item.title}}</div>
		</div>
	</div>
</template>

<script>
	import html2canvas from 'html2canvas'
	import jsPDF from 'jspdf'
	export default {
		data() {
			return {
				data: [{
					title: '这是第一页',
				}, {
					title: '这是第二页',
				}]
			}
		},
		components: {

		},
		methods: {
			async print() {
				const el = this.$refs.box.$el
				html2canvas(el, {
					logging: false,
					background: '#fff',
					allowTaint: true,
					taintTest: false,
					height: el.scrollHeight,
					width: el.scrollWidth,
					useCORS: true, //允许canvas画布内可以跨域请求外部链接图片, 允许跨域请求。
					dpi: 300, // 提升导出的文件的分辨率
					scale: 5
				}).then(canvas => {
					var canvasWidth = canvas.width; //图片容器宽度
					var canvasHeight = canvas.height; //图片容器高度
					let pagesHeight = '' //页面高度
					let leftHeight = canvasHeight //未生成pdf的高度
					var position = 0 //页面偏移
					var imgWidth = 0
					var imgHeight = 0
					pagesHeight = canvasWidth / 592.28 * 841.89
					imgWidth = 592.28;
					imgHeight = 592.28 / canvasWidth * canvasHeight;
					var pdf = new jsPDF('', 'pt', 'a4', true);
					var pageData = canvas.toDataURL('image/jpeg', 1.0);
					//有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
					//当内容未超过pdf一页显示的范围,无需分页
					if (leftHeight < pagesHeight) {
						pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight, '', 'FAST')
					} else {
						while (leftHeight > 0) {
							pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight, '',
								'FAST')
							leftHeight -= pagesHeight;
							position -= 841.89;
							//避免添加空白页
							if (leftHeight > 0) {
								pdf.addPage();
							}
						}
					}
					pdf.save('1')
//此处为保存到本地的pdf操作,如果需要上传到服务器的话,则在这个位置加入第三步代码替换pdf.save('1')
				})
			},
		}
	}
</script>
<style>
	.btn {
		height: 50px;
		display: flex;
		align-items: center;
		justify-content: center;
		background-color: palegreen;
	}

	.box {
		background-color: paleturquoise;
		font-size: 18px;
		font-weight: 700;
		width: 592px;
	}

	.box .item {
		height: 841px;
	}
</style>

第三步:以上代码只能简单的实现转pdf后下载到本地,如果需要实现通过后端接口上传到服务器的话, 则需要转base64后通过转文件流的形式调用后端接口上传到服务器

①将此处代码替换第二步中的pdf.save('1')

let base64 = pdf.output("datauristring")
let file = this.convertBase64ToFile(base64, '转pdf的文件名称')

②以下方法为将pdf转化为file文件流代码

// base64转文件
			convertBase64ToFile(urlData, filename) {
				var arr = urlData.split('base64,');
				var type = arr[0].match(/:(.*?);/)[1];
				var fileExt = type.split('/')[1];
				var bstr = atob(arr[1]);
				var n = bstr.length;
				var u8arr = new Uint8Array(n);
				while (n--) {
					u8arr[n] = bstr.charCodeAt(n);
				}
				return new File([u8arr], filename + "." + fileExt, {
					type: type
				});
			},

 第四步:可以结合element中的upLoad实现上传,以下实例为使用uniapp中的uni.uploadFile()实现文件的上传

①uniapp中的uni.uploadFile()实现文件的上传

uni.uploadFile({
						url: 'xxxx', //上传地址
						file: file, //文件对应第三步中的let file = this.convertBase64ToFile(base64, '转pdf的文件名称')
						name: 'file',
						formData: {
							id: '123456',
						}, //其他参数
						success: () => {

						} //成功后的回调
					})

②其他上传实现可参考element组件或者原生请求方式(后续有时间再进行更新)

猜你喜欢

转载自blog.csdn.net/A1123352950/article/details/132511461