在整理自己的工作笔记时,看到了这篇文章,决定发布出来和大家共享,希望能够帮助到你。
现象
使用 JsPdf 导出 PDF 文件后,用WPS对其进行打印,打印机卡死重启,而使用AdobePDF阅读器打印,则没有问题。
JsPdf 是使用 html2Canvas 裁剪图片导出至PDF文件,文件头信息版本号为V1.3。
尝试使用WPS打印
- 纯图片(5M)打印成功。
-
将5M图片转为base64,再由JsPDF导出为PDF文件,边界值(600*600)打印成功,边界值(595.28 * 1728)打印成功。
-
将PDF内容置空,导出2页空白PDF,打印成功。
-
将PDF第一页内容置空,将答题卡PNG/JPEG图片转为base64,载入PDF第二页,边界值(600*600)打印成功,边界值(595.28 * 1728)打印成功。
-
将PDF第一页使用Canvas裁剪,将答题卡PNG/JPEG图片转为base64,载入PDF第二页(共915KB),边界值(595.28 * 1728)打印失败。
-
PDF打印一页使用Canvas裁剪,打印成功。
-
将PDF第一页使用Canvas裁剪,将答题卡PNG/JPEG图片转为base64,载入PDF第二页(共915KB),边界值(600 * 600)打印失败。
-
PDF.addPage().addImage() 载入图片,边界值(595.28 * 1728)打印失败。
-
将PDF第一页内容置空,使用Canvas只裁剪第二页内容,载入PDF第二页,边界值(595.28 * 1728)打印失败。
-
将a4纸的尺寸[595.28,841.89],之前高度是871.89 修改为 841.89,打印失败。
-
先PDF.addPage(),再PDF.addImage(),打印失败。
-
只渲染一页答题卡,都使用Canvas裁剪,先PDF.addPage()添加第一页空页面,代码强制分2页(共500KB),打印成功。
-
渲染两个答题卡,先PDF.addPage()添加第一页空页面,代码强制分2页。测试下只裁剪第一页进行打印,边界值(595.28 * 1728)(共685KB),打印失败。
-
将所有分页dom取出,再循环html2canvas裁剪成图片,PDF.addIamge()两页(共713KB),打印成功。
总结
当答题卡内容只有一页时,html2canvas转成图片,再将其载入A4尺寸的PDF中,是正确的。
当答题卡内容超过一页时,html2canvas转成图片(长图片),其尺寸已超过A4尺寸,这么时候再载入PDF中,虽然PDF内容显示是正确的,但是其不会对图片进行裁剪,只是依据A4尺寸显示了图片A4大小的内容,这就会隐性的出现图片实际比PDF页大,那么再使用WPS或浏览器打印时,打印机重启或卡死。
解决办法
const PDF = new JsPDF('', 'pt', 'a4', true);
Promise.all(getImagesData()).then(imgs => {
for (let i = 0, len = imgs.length; i < len; i++) {
i > 0 && PDF.addPage(); // PDF增加空白页
let canvas = imgs[i];
let pageData = canvas.toDataURL('image/jpeg', 1);
// a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
const imgWidth = 595.28;
const imgHeight = parseInt(imgWidth / canvas.width * canvas.height);
PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);
}
PDF.save(title + 'pdf');
})
// 获取当前答题卡分页后的图片函数对象
function getImagesData() {
let imagesData = [];
let sheets = document.querySelectorAll('.answerSheet');
for (let i = 0, len = sheets.length; i < len; i++) {
imagesData.push(html2Canvas(sheets[i], {
allowTaint: true,
taintTest: false,
useCORS: true,
async: true,
scale: '2',
}).then(canvas => {
return canvas;
}, error => {
return false;
}));
}
return imagesData;
}