VUE使用JsPDF+html2Canvas实现前端生成PDF文件

1.需求

前端需要自己把当前页面或者某个盒子的内容导出成PDF文件并下载

2.工具下载

安装jspdf: npm install jspdf --save

安装html2Canvas: npm install --save html2canvas

3.封装方法

先建一个downloadHtmlToPdf.js文件,然后再main.js中全局引用即可

//main.js引用 也可以单独引用
import downloadHtmlToPdf from '@/util/downloadHtmlToPdf'
Vue.use(downloadHtmlToPdf)

 downloadHtmlToPdf.js

import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'

export default {
	install(Vue, options) {
		Vue.prototype.downloadHtmlToPdf = function () {
			var pdfName = this.htmlTitle
			html2Canvas(document.querySelector('#printer'), {
				scale: 4, // 提升画面质量,但是会增加文件大小
				useCORS: true, // 允许跨域图片 当图片是链接地址时,需加该属性,否组无法显示图片
				dpi: 300 // 将分辨率提高到特定的DPI
			}).then((canvas) => {
				// A4大小,210mm x 297mm,四边各保留10mm的边距,显示区域190x277
				const A4_WIDTH = 190
				const A4_HEIGHT = 277

				// 画布的尺寸
				const contentWidth = canvas.width
				const contentHeight = canvas.height

				// 一页 pdf html 页面生成的 canvas 高度;
				const pageHeight = Math.floor(contentWidth / A4_WIDTH) * A4_HEIGHT
				// 未生成 pdf 的 html 页面高度
				let leftHeight = contentHeight

				// 页面偏移
				let position = 0
				const pageData = canvas.toDataURL('image/jpeg', 1.0)
        // const pdf = new JsPDF('p', 'mm', 'a4') // A4纸,纵向

        //此处判断是否大于一页,如果小于一页,则动态设置页面高度
        let pdf;
        if(contentHeight/contentWidth < A4_HEIGHT/A4_WIDTH){
          let h = Math.max(210/contentWidth*contentHeight, 210);//最低210
          pdf = new JsPDF('p', 'mm', [210, h])
        }else{
          pdf = new JsPDF('p', 'mm', 'a4') // A4纸,纵向
        }

				// index = 1,
				let canvas1 = document.createElement('canvas'),
					height
				pdf.setDisplayMode('fullwidth', 'continuous', 'FullScreen')

				function createImpl(canvas) {
					if (leftHeight > 0) {
						// index++
						var checkCount = 0
						if (leftHeight > pageHeight) {
							var i = position + pageHeight
							for (i = position + pageHeight; i >= position; i--) {
								var isWrite = true
								for (var j = 0; j < contentWidth; j++) {
									var c = canvas.getContext('2d').getImageData(j, i, 1, 1).data
									if (c[0] != 0xff || c[1] != 0xff || c[2] != 0xff) {
										isWrite = false
										break
									}
								}
								if (isWrite) {
									checkCount++
									if (checkCount >= 10) break
								} else {
									checkCount = 0
								}
							}
							height = Math.round(i - position) || Math.min(leftHeight, pageHeight)
							if (height <= 0) {
								height = pageHeight
							}
						} else {
							height = leftHeight
						}
						canvas1.width = contentWidth
						canvas1.height = height
						var ctx = canvas1.getContext('2d')
						ctx.drawImage(canvas, 0, position, contentWidth, height, 0, 0, contentWidth, height)
						if (position != 0) {
							pdf.addPage()
						}
						pdf.addImage(
							canvas1.toDataURL('image/jpeg', 1.0),
							'JPEG',
							10,
							10,
							A4_WIDTH,
							(A4_WIDTH / canvas1.width) * height
						)
						leftHeight -= height
						position += height
						if (leftHeight > 0) {
							setTimeout(createImpl, 500, canvas)
						} else {
							pdf.save(pdfName + '.pdf')
						}
					}
				}

				// 当内容未超过pdf一页显示的范围,无需分页
				if (leftHeight < pageHeight) {
					// 在 pdf.addImage(pageData, 'JPEG', 左,上,宽度,高度) 设置在pdf中显示;
					pdf.addImage(pageData, 'JPEG', 10, 10, A4_WIDTH, (A4_WIDTH / contentWidth) * contentHeight)
					pdf.save(pdfName + '.pdf')
				} else {
					// 分页
					try {
						pdf.deletePage(0)
						setTimeout(createImpl, 500, canvas)
					} catch (err) {
						// reject()
					}
				}
			})
		}
	}
}

4.怎么使用,适用范围

上面封装的方法适用pc端和移动端,但只能在浏览器为引擎的项目,就是说在浏览器中打开此项目都是可以正常导出PDF文件的

使用方式

<template>
    <div>
        <div id="printer">
            要导出的盒子,需要加id(printer)
        </div>
        <div @click="downloadHtmlToPdf">导出pdf</div>
    </div>
</template>

5.问题

在浏览器打开是可以正常下载PDF文件的,但是移动端入口是从某个APP进入的,没在浏览器上运行,就会导致PDF文件直接打开的情况,但并没有下载。

导出PDF文件的方法是 pdf.save(pdfName + '.pdf') 这个方法在这种情况下导出PDF文件有问题,需要换一种写法

//pdf.save(pdfName + '.pdf')方法换成下面用a标签下载
//转成文件流的形式下载
var pdfData = pdf.output('datauristring')
var a = document.createElement('a')
a.href = pdfData 
a.download = '文件名.pdf'
a.click()
a.parentNode.removeChild(a)

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值