前言
最近遇到个需求,需要前端将页面以PDF的形式下载下来,并且支持批量下载,所以实现后,在此做个记录,希望可以帮助到更多的同学;
前置依赖
$ yarn add html2canvas jspdf jszip file-saver
截图
截图选用 html2canvas
文件名screenshots.js
import html2canvas from 'html2canvas';
import { fileToPDF } from './fileUtils';
/* eslint-disable no-undef */
/**
* [saveImg description]
*
* @param {[dom|object]} el [el description]
* @param {[params]} params name: 文件名字, type, fileType
*
* @return {[Promise]} [return Promise]
*/
function saveImg(el, { name, type, fileType }) {
return new Promise((resolve, reject) => {
let dom = el;
if (!el.nodeName) {
dom = el.el;
}
// 获取元素样式
const box = window.getComputedStyle(dom);
// DOM 节点计算后宽高
const width = parseValue(box.width);
const height = parseValue(box.height);
// 获取像素比
const scaleBy = DPR();
// 创建自定义 canvas 元素,设置高清图片
const canvas = document.createElement('canvas');
canvas.width = width * scaleBy;
canvas.height = height * scaleBy;
// 设定 canvas css宽高为 DOM 节点宽高
canvas.style.width = `${width}px`;
canvas.style.height = `${height}px`;
// 获取画笔
const context = canvas.getContext('2d');
context.scale(scaleBy, scaleBy);
html2canvas(dom, {
canvas,
backgroundColor: 'transparent',
useCORS: true
}).then(function(canvas) {
// 获取图片的base64
if (type !== 'pdf') {
const toDataURL = canvas.toDataURL(type, 1.0);
resolve(toDataURL);
} else {
const pageData = canvas.toDataURL(type || 'image/png', 1.0);
// console.log(pageData);
const obj = {
pageData,
canvas,
name,
type: fileType || 'base64'
};
resolve(fileToPDF(obj));
}
});
});
}
// 四舍五入及计算数值
function parseValue(value) {
return parseInt(value, 10);
}
// 获取像素比
function DPR() {
if (window.devicePixelRatio && window.devicePixelRatio > 1) {
return window.devicePixelRatio;
}
return 1;
}
export default saveImg;
图片转换成PDF
文件名 fileUtils.js
import JsPDF from 'jspdf';
/**
*
* @param {*} pageData 页面数据
* @param {*} canvas canvas 元素
* @param {*} name 文件名
* @param {*} type 文件类型
* @returns
*/
export const fileToPDF = ({ pageData, canvas, name, type }) => {
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 = 595.28 / contentWidth * contentHeight;
const pdf = new JsPDF('', 'pt', 'a4');
// 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
// 当内容未超过pdf一页显示的范围,无需分页
if (leftHeight < pageHeight) {
// 在pdf.addImage(pageData, 'JPEG', 左,上,宽度,高度)设置在pdf中显示;
pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);
// pdf.addImage(pageData, 'JPEG', 20, 40, imgWidth, imgHeight);
} else { // 分页
while (leftHeight > 0) {
pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight);
leftHeight -= pageHeight;
position -= 841.89;
// 避免添加空白页
if (leftHeight > 0) {
pdf.addPage();
}
}
}
const pdffile = pdf.output('datauristring');
if (type && type === 'base64') {
return pdffile;
}
const blob = dataURLtoFile(pdffile, name);
return blob;
};
// 文件转换成blob类型
function dataURLtoFile(dataurl, filename) {
var arr = dataurl.split(',');
var mime = arr[0].match(/:(.*?);/)[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, { type: mime });
}
文件压缩下载与批量下载
文件名 fileUtils.js
import JSZip from 'jszip';
import FileSaver from 'file-saver';
/**
*
* @param {*} fileName 文件名字,支持数组
* @param {*} content 文件内容,支持数组
* @param {*} downName 下载文件夹名称
* @param {*} fileType 文件传输类型
*/
export const download = (fileName, content, downName, fileType) => {
console.log('---- 开始压缩下载 ----');
const zip = new JSZip();
const imgTypes = ['gif', 'jpg', 'jpeg', 'png', 'pdf'];
const setZipFile = (name, _content) => {
const type = name.split('.').pop();
if (imgTypes.includes(type) || fileType === 'base64') {
zip.file(name, _content, { base64: true });
} else {
zip.file(name, _content);
}
};
// 如果是数组需要依次生成
if (Object.prototype.toString.call(fileName) === '[object Array]') {
fileName.forEach((value, key) => {
setZipFile(value, content[key]);
});
} else {
setZipFile(fileName, content);
}
// 保存生成压缩包
zip.generateAsync({ type: 'blob' })
.then((content) => {
const time = new Date().getTime();
FileSaver(content, `${downName ? downName + '-' + time : time}.zip`);
});
};
综合使用
import saveImg from './screenshots';
import { download } from './fileUtils';
const el = document.querySelector('#app')
const img1 = await saveImg(el, { type: 'pdf', name: 'ceshi.pdf', fileType: 'blob' });
const img2 = await saveImg(el, { type: 'pdf', name: 'ceshi2.pdf', fileType: 'blob' });
// 多数据转换下载,需要内容与名称一一对应
const pdfArr = [img1, img2];
const pdfNames = ['ceshi1.pdf', 'ceshi2.pdf'];
download(pdfNames, pdfArr, '压缩下载', 'base64');
// 单个数据下载
download('ceshi1.pdf', img1, '压缩下载', 'base64');
以上就是本次的内容了,希望可以帮助到大家