后端技术选用
传统Excel操作或者解析都是利用Apach POI进行操作,但是使用过这个框架的人都知道,这个框架并不完美,有较多的缺陷:
- 使用步骤繁琐
- 动态写出Excel操作非常麻烦
- 对于新手来说,很难在短时间内上手
- 读写时需要占用较大的内容,当数据量大时容器发生OOM
基于上述原因,阿里开源出一款易上手,且比较节省内存的Excel操作框架:EasyExcel
apache POI
java实现导入导出Excel文件
easyexcel (推荐)
官方文档:https://www.yuque.com/easyexcel/doc/easyexcel
java使用阿里的easyExcel实现Excel导出/导入功能
使用easyexcel完成复杂表头及标题的导出功能(自定义样式及多sheet导出)
后台部署到docker中还需要注意安装字体,打包时依赖镜像aesopcmc/openjdk:8-jdk-alpine-font
, 例如:
echo "
FROM aesopcmc/openjdk:8-jdk-alpine-font
COPY ./${jarName}.jar /usr/local/app/
WORKDIR /usr/local/app/
CMD java -Djava.security.egd=file:/dev/./urandom -jar -Duser.timezone=GMT+08 ${jarName}.jar --spring.profiles.active=${active}
" > Dockerfile
否则会报错:
java.lang.NullPointerException: null
at sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264) ~[na:1.8.0_212]
...
前端实现下载文件
前端使用vue + axios 请求后台获取文件流下载文件:
1.在 utils/api.js中配置请求,下载文件专用
//文件下载专用请求配置(通常用于excel导出、文件下载)
export async function $postExcel(url, obj = {}) {
console.log("obj", obj);
/* request payload */
return await axios({
method: "post",
url: process.env.BASE_URL+url,
responseType: 'blob', // 请求为blob类型
headers: {
'session': "",
"Content-Type": "application/json"
},
transformRequest: [
function (data) {
return data;
}
],
data: obj
}).then(res=>{
return res.data
}).catch(catchError)
}
let catchError = error => {
console.error('err' + error)// for debug
Message({
message: error.message,
type: 'error',
duration: 3 * 1000
})
return Promise.reject(error)
}
- 在main.js中挂载
import {$postExcel} from './utils/api'
Vue.prototype.$postExcel = $postExcel
- 在文件中使用
<el-button type="primary" @click="handleExportExcel" :loading="exportLoading">导出Excel</el-button>
async handleExportExcel() {
this.exportLoading = true
const data = await this.$postExcel('/order/listExportExcel/', this.listQuery)
let fileName = 'Excel表模板.xlsx' // xlsx和xls都是支持的
// 通过创建a标签实现文件下载
let link = document.createElement('a')
link.download = fileName
link.style.display = 'none'
link.href = URL.createObjectURL(data)
document.body.appendChild(link)
link.click()
URL.revokeObjectURL(link.href) // 释放URL 对象
document.body.removeChild(link)
this.exportLoading = false
},