在react项目中,截取订单表生成pdf并上传,花了一个星期熬出来一部分,(还差上传部分,因为后台接口问题,一直没有转成后台想要的格式,。。。。)
记录一笔
html2canvas
"html2canvas": "^1.0.0-rc.7", 我使用的版本,期间也使用过其他版本的,自己技术不求行,坑多啊啊
html2canvas options属性
简单使用,document是要截取的html片段(dom对象),options参数
document = document.getElementsByClassName('....')
options = {
scale:2,//放大倍数 解决清晰度的问题
useCORS: true,//涉及到截取的dom中有跨域存在时 一定要使用
}
html2canvas(document,options).then(function(canvas) {
//canvas 返回生成的canvas
})
jspdf
"jspdf": "^2.2.0", 我使用的版本, 参数设置也是坑的一批,宽高偏移什么的怎么设置都不是自己想的,最后全凭感觉了(太菜了)
jspdf-Documnet 一个英文api文档
jspdf 属性
简单使用,具体可以参照api,还有网上很多大佬使用的记录
//第一个参数 p/l 控制横屏或是竖屏 默认值 p
//第二个参数 单位。其中一个"pt"(点),"mm"(默认),"cm", "in", "px"
//第三个参数 pdf的尺寸 默认是 a4纸的大小 也可以自定义 【w,h】
let pdf = new jsPDF('', 'pt', 'a4')
let pdf = new jsPDF('', 'pt', [595.28, pageArr[0].height])
// pdf.addImage(pageData, 'JPEG', 左,上,宽度,高度)设置
pdf.addImage(pageData, 'JPEG', 20, 0, imgWidth, imgHeight)
pdf.save('hahah.pdf')// 下载
功能实现的具体使用
在我的代码中,我固定了dom容器的宽度为a4纸的宽,高度自适应,附带一个表格边框的样式,为什么要自己写表格样式、、、、因为坑啊
<div className="dom">
<table className='pdftable'>.......</table>
</div>
.dom{
width: 595.28px;
margin:30px auto; /*no*/
background-color: white;
position: relative;
}
//表格边框样式
.pdftable {
width: 595.28px;
border:1px solid #444;
border-top: none;
border-spacing: 0;
}
.pdftable td{
border-right: 1px solid #444;
border-bottom: 1px solid #444;
}
.pdftable tr td:last-child{ border-right: 0 }
.pdftable tr:last-child td{ border-bottom: 0 }
react中生成pdf的方法代码---------------------------------------------------------------------------------------------
const creatPdf= (htmlFlag, isOne) => {
let htmls = Array.from(document.getElementsByClassName('pdftable'))
console.log(htmls)
let pageArr = []
htmls.forEach(html => {
let contentWidth = html.clientWidth // 获得该容器的宽
let contentHeight = html.clientHeight // 获得该容器的高
let canvas = document.createElement('canvas')
let scale = 2 // 解决清晰度问题,先放大 2倍
canvas.width = contentWidth * scale // 将画布宽&&高放大两倍
canvas.height = contentHeight * scale
let content = canvas.getContext("2d")
// content.scale(scale, scale) 如果canvas有偏移的话 可以考虑使用注释的这个来调动
// let rect = html.getBoundingClientRect()
// console.log(rect)
// content.translate(0, -rect.y / scale)
// content.translate(0, 10)
let opts = {
scale: scale,
canvas: canvas,
background: '#fff',
width: contentWidth,
height: contentHeight,
useCORS: true,
imageTimeout: 60000,
}
html2canvas(html, opts).then(canvas => {
let pageData = canvas.toDataURL('image/jpeg', 1.0)
pageArr.push({ src: pageData, width: contentWidth, height: contentHeight })
if (pageArr.length === htmls.length) {
let pdf = new jsPDF('', 'pt', [595.28, pageArr[0].height])
pageArr.forEach((page, index) => {
console.log(page, index)
if (index !== 0) {
pdf.addPage()
}
// a4纸的尺寸[595.28,841.89]
let pdfHeight = page.height
let pdfWidth = page.width
if (page.height > 841.89) {
pdfHeight = page.height // 841.89
pdfWidth = 595.28
}
pdf.addImage(page.src, 'JPEG', 4, 8, pdfWidth - 16, pdfHeight - 16)
// let pdf = new jsPDF('', 'pt', 'a4') // 下载尺寸 a4 纸 比例
console.log(page.width, 'contentWidth')
console.log(page.height, 'contentHeight')
// pdf.addImage(pageData, 'JPEG', 左,上,宽度,高度)设置
})
setTimeout(() => {
pdf.save(`test.pdf`)
}, 100)
}
})
})
上传后台的话还没有调通接口,暂时前端能使用的方法可以粘出来、、、
在截取页面表格,生成pdf后,转成后台需要的格式上传 (注意后台需要参数的数据类型 例如form…)
1.把pdf转成 blob格式
const blob= pdf.output("blob");
const formData = new FormData();
formData.append("file", pdf);
//formData 上传的请求参数
2.pdf先转base格式的字符串,再将base64格式的字符串转换为file文件
// 处理方法
const dataURLtoFile = (dataurl, filename) => {
let arr = dataurl.split(',');
let mime = arr[0].match(/:(.*?);/)[1];
let bstr = atob(arr[1]);
let n = bstr.length;
let u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
//转换成file对象
return new File([u8arr], filename, {type: mime});
//转换成成blob对象
// return new Blob([u8arr],{type:mime});
};
let base64= pdf.output("datauristring");
let myfile = dataURLtoFile(base64, fileName);
let formData = new FormData();
formData.append('newFile', myfile);
//formData 上传的请求参数
3.另一种base64的方式
let datauri = pdf.output('dataurlstring')
let base64 = datauri.substring(28)
let formData = new FormData()
formData.append('newFile', base64)