涉及的技术: react、jspdf、file-saver
思想: 使用文件流进行解析然后进行页面渲染
具体实现代码如下:
html部分:
<Button onClick={handleDownLoad}>下载</Button>
JS部分:
//点击下载的方法
const handleDownLoad=()=>{
const pdfRender = new PagePdfRender({
...params //参数
})
// 开始页面的渲染
pdfRender.generate({
type: 'blob',
onSuccess: async()=>{
// 下载到本地
const FileSaver = require('file-saver')
FileSaver.saveAs(url,'文件名称')
}
})
}
//PagePdfRender 文件内容
import jdPDF from 'jspdf'
import autoTable from 'jspdf-autotable'
import moment from 'moment'
const getRatio =()=>2481/595
const px2A4 = (val: number)=>{
return val/getRatio()
}
class PagePdfRender {
public doc;
public info //传进来的值
constructor(v){
this.info = v;
this.doc = new jsPDF('p','pt','a4',true)
}
}
//页面初始化一些文字,避免加载出文字乱码
async init(){
await this.loadFont('*******.ttf','normal')
await this.loadFont('*******.ttf','bold')
await this.loadFont('*******.ttf','light')
}
//创建元素
createElement(targetName: string,opt: any){
const el = document.createElement(targetName)
el.style.position = 'absolute';
el.style.bottm = '9999'
if(opt.className) el.className = opt.className
if(opt.innerHTML){
el.insertAdjacentHTML('afterbegin',opt.innerHTML)
}
for(const key in opt.style){
el.style[key] = opt.style[key]
}
document.body.appendChild(el)
return new Promise((resolve)=>{
setTimeOut(()=>{
resolve(el)
},50)
})
}
//移除元素
removeElement(el: any){
document.body.removeChild(el)
}
//渲染主要导出的内容
async drawPage(){
const htmlStr += '<div>我是pdf内容</div>'
const element = (
await this.createElement(
'div',{
innerHTML: htmlStr
}
)
) as HTMLElement
autoTable(this.doc,{
html: '#****',
theme: 'grid',
useCss: true,
styles: {
font: 'MyFont',
fontStyle: 'normal',
halign: 'center',
valign: 'top',
minCellWidth: 50
}
})
this.removeElement(element)
}
//流文件渲染
toBlob() {
return this.doc.output('blob');
}
async generate(option?:{
onProcess?: (current: number)=> void;
onSuccess?: (url: string| Blob)=>void
}){
await this.init();
await this.drawPage();
const blob = this.toBlob()
option?.onSuccess?.(blob)
return blob
}