赞
踩
参考文章:实测可行、但是需要修改
前端vue的JsPDF html2canvas 生成pdf并以文件流形式上传到后端
项目背景:vue2
框架:若依
需求:把页面上某一块内容(或者整个页面),转为pdf文件上传到后端、或者下载到本地
提示:以下是本篇文章正文内容,下面案例可供参考
npm i html2canvas --save
npm i jspdf --save
代码如下(示例):
需要修改id为你的页面上内容的id
我这里是#printer
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('#printer'), { 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'; // 下载+上传
Vue.use(htmlToPdf);
这个是base64转blob,不是base64加密
// 转换为 Blob 对象的方法 (可复用) export function base64ToBlob(base64Data) { const parts = base64Data.split(";base64,"); const contentType = parts[0].split(":")[1]; const raw = window.atob(parts[1]); 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: contentType }); } // 从 base64 数据中获取文件名和 mime 类型的方法 (可复用) export function getFilenameAndMimetypeFromBase64(base64Data) { const fileInfo = base64Data.split(';base64,')[0].substring(5).split(':'); const mimeType = fileInfo[0]; const filename = fileInfo[1]; return [filename, mimeType]; }
只是api方法示例,基本上vue框架,都会封装request.js,如果看不懂,可以翻原文
import request from '@/utils/request';
// 上传签名图片 || 上传手写意见图片
export function uploadSign(data) {
return request({
url: '/flow/common/upload',
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
},
data: data,
});
}
我这里需要可复用性,所以关键性都在utils中,
import { uploadSign } from '@/api/flow/common.js';
import { base64ToBlob, getFilenameAndMimetypeFromBase64 } from '@/utils/base64.js';
// getFilenameAndMimetypeFromBase64 可以不用
// 因为我指定了上传文件是pdf,所以不需要去查找是什么类型
需要id
和utils/htmlToPdf.js
中的对应
<el-button type="primary" icon="el-icon-printer" @click="toGetPdf(0)">只下载</el-button>
<el-button type="warning" icon="el-icon-printer" @click="toGetPdf(1, 0)">只上传</el-button>
<div id="printer" class="table">
...
</div>
// 保存方法 toGetPdf(val = false, download = true) { /** * val 决定走不走上传接口,默认为不上传给后端 * download 默认是下载 * / /* */ this.$nextTick(() => { setTimeout(() => { window.scrollTo(0, 0); //这行代码很重要,它让页面的滚动条跳到了最上方如果点击打印按钮的时候, // 滚动条没有在最上方,打印内容会是不完整的,体验也会差 let title = '个人报告'; this.getPdf(title, download) //download:false为不下载,这里调用了刚刚引用的全局函数, // .then得到的值是base64位的pdf文件 .then((res) => { if (val) { console.log('准备上传'); this.UploadPdf(res); } else { console.log('不上传'); } }); }, 1000); }); }, //上传pdf接口 UploadPdf(res) { //res拿到base64的pdf let pdfBase64Str = res; let filename = '测试.pdf'; // 将 base64 编码的文件数据转为 Blob 对象 const blob = base64ToBlob(pdfBase64Str); // 获取文件名和 mime 类型 // const [filename, mimeType] = getFilenameAndMimetypeFromBase64(res); // 将 Blob 对象转换为 File 对象 const file = new File([blob], filename, { type: '.pdf' }); // type类型对应的是mimeType // 上传文件 const formData = new FormData(); formData.append('file', file); formData.append('name', filename); //该uploadMy为接口,直接以formdata格式传给后台 uploadSign(formData) // 改为你自己的上传接口 .then((res) => { console.log('上传pdf接口', res); }) .catch((err) => { console.log('上传pdf接口', err); }); },
如有不懂,请看原文。
我这里是基于原文实现,并且修改部分内容。
js指定页面内容另存为pdf文件
前端vue把页面转为file文件流上传到后端
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。