功能描述:
react项目中,需要做一个功能:点击下载按钮,将包含echarts图表和表格的报告以word形式下载。
解决方案:
前端将报告切割成图片,这里切割成两张,图片以base64形式 post传给服务端,服务端转化为图片写入word并返回
用到的技术:
html2canvas
具体方法:
1.首先安装引入html2canvas
npm install html2canvas
import html2canvas from 'html2canvas'
具体使用方法参照官方文档 http://html2canvas.hertzen.com/getting-started
2.html部分
<Button type="primary" onClick={this.download}>下载</Button>
3.点击事件
convertCanvasToImage = (canvas, flag) => {
let image = new Image();
image.src = canvas.toDataURL("image/png");
image.className = (flag === 'report') ? 'img report' : 'img ks'
let pic = (flag === 'report') ? document.getElementsByClassName('report') :
document.getElementsByClassName('ks')
if(pic.length > 0) {
return
}
document.body.appendChild(image)
return image
}
download = () => {
const {dispatch} = this.props
var cntElem = $("#chartReport")[0]
var shareContent = cntElem;//需要截图的包裹的(原生的)DOM 对象
var opts = {
// scale: scale, // 添加的scale 参数
// canvas: canvas, //自定义 canvas
// // logging: true, //日志开关,便于查看html2canvas的内部执行流程
// width: width, //dom 原始宽度
// height: height,
// useCORS: true // 【重要】开启跨域配置
};
const that = this
const chartReport = html2canvas(shareContent, opts).then(function(canvas) {
//var context = canvas.getContext('2d');
//关闭抗锯齿
//context.mozImageSmoothingEnabled = false;
//context.webkitImageSmoothingEnabled = false;
//context.msImageSmoothingEnabled = false;
//context.imageSmoothingEnabled = false;
that.convertCanvasToImage(canvas, 'report')
});
const chartKs = html2canvas($("#chartKs")[0]).then(function(canvas) {
that.convertCanvasToImage(canvas, 'ks')
});
Promise.all([chartReport, chartKs])
.then(result => {
let src = []
$('.img').each(function(e, i) {
let $src = $(this).attr('src')
src.push($src)
})
const param = {
base64_pie: src[0],
base64_bar:src[1],
}
dispatch({
type: 'message/exportReport',
payload: param
})
})
.catch(e => console.log(e))
}
4.设置post请求,服务端header设置Content-Type: application/msword,
常用对照表:http://tool.oschina.net/commons/
export async function exportReport(params) {
return request('/webservice/dashboard/exportReport', {
method: 'POST',
responseType: 'blob', //设置type
body: params,
});
}
request.js,注意:fetch返回的response正常情况下调用json()生成json数据。但是在这里,我们需要用到blob对象,因此要调用blob()或者arrayBuffer()。
return fetch(url, newOptions)
.then(checkStatus)
.then(response => {
/*if (newOptions.method === 'DELETE' || response.status === 204) {
return response.text();
}*/
if(newOptions.responseType === 'blob') {
return response.blob()
}
return response.json().then(res => {
if(res.httpCode == '401') { //未登录
window.location.href = res.url
}
return res
})
})
models
* exportReport ({payload}, {call, put, select}) {
const {title} = yield select(_ => _.message)
const data = yield call(exportReport, payload)
if(data instanceof Blob) {
let fileName = 'aaa.doc'
if (window.navigator.msSaveOrOpenBlob) {
navigator.msSaveBlob(data, fileName);
} else {
var link = document.createElement('a');
link.href = window.URL.createObjectURL(data);
link.download = title
document.body.appendChild(link);
var evt = document.createEvent("MouseEvents");
evt.initEvent("click", false, false);
link.dispatchEvent(evt);
document.body.removeChild(link);
//使用window.open(url)时,不知为何获取不到服务端传回的fileName
// const url = window.URL.createObjectURL(data);
// window.open(url)
}
}
},