环境:
前端: Ant Design of Vue(UI) + Vue + axios接口调用
后端:EasyExcel实现Excel表格的读写操作。
目录:
导入Excel文件
导出Excel文件
流程:
下载模板->编写Excel数据文件->触发导入数据->发送axios请求->后端接收数据->数据持久化(数据处理)
在导入文件之前需要用户根据自己设定的Excel模板进行填写数据.(模板字段对应后端实体类字段)
模板创建可参考上一篇文章EasyExcel简单读写Excel操作 https://blog.csdn.net/whitehats/article/details/111614450
上传按钮使用的是AntdVue中的上传按钮,设置beforeUpload函数进行上传文件操作(具体可以根据自己需求更改UI设计)
<a-upload
:beforeUpload="beforeUpload"
:showUploadList="false"
:multiple="true">
<a-button type="primary"> 导入线索 a-button>
a-upload>
这里需要注意的是数据是以FormData的形式进行传输的,注意!!!需要设置在请求头中添加"Content-Type":“multipart/form-data”。**
beforeUpload(file){
let _this = this
console.log(file)
let formData = new FormData();
formData.append("file", file);
let config = {
headers: {
"Content-Type": "multipart/form-data",
}
};
let url = "/importData" //这里填写调用的后端Excel数据处理接口
this.$axios.post(url, formData, config).then(response => {
let data = response.status;
console.log(data)
if (response.status == 200) {
alert('导入成功');
return;
}else{
alert("导入失败");
return;
}
}).catch(function(error){
alert("导入失败");
});
},
注意:在后端导入方法传入的参数为MultipartFile数据类型,获取到file文件转换为文件流并通过invoke方法按照所对应的实体类(ClueDTO) 逐行的数据进行获取。(EasyExcel进行读操作)
public Results<Object> importData(@RequestParam("file") MultipartFile file) throws IOException {
if (file == null) new Results<>(404,"导入数据失败",null);
ArrayList<Object> list = new ArrayList<>();
AnalysisEventListener listener = new AnalysisEventListener() {
@Override
public void invoke(Object data, AnalysisContext context) {
//获取到每一行数据,逐行进行处理
list.add(data);
ClueDTO clueDTO = (ClueDTO)data;
Clue clue = new Clue();
BeanUtils.copyProperties(clueDTO,clue);
//这里将获取到的数据封装回实体类对象中,并在数据库持久化
clueService.addClue(clue);
System.out.println(Arrays.toString(new ArrayList[]{list}));
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
log.info("导入数据完毕");
}
};
try {
EasyExcel.read(file.getInputStream(), ClueDTO.class, listener).sheet(0).doRead();
} catch (IOException e) {
log.error("导入出错:{}", e.getMessage());
}
return new Results<>(200,"导入数据成功",list);
}
以上导入Excel文件基本完成。
流程:
触发导出->前端封装数据->发送axios导出请求->后端进一步封装数据->响应给前端
<a-button type="primary" @click="exportData">
导出线索
a-button>
点击按钮触发导出函数。这里需要注意的是在调用axios时,注意!!!需要设置返回类型responseType:“blob” ,以文件的形式返回。在响应方法中,将后端返回的数据封装为blob,同样注意!!!需要设置type: “multipary/form-data”,并通过超链接的形式自动触发下载响应.
//导出数据
exportData(){
this.$axios({
method: "post",
url: "/exportData",
data:this.clueList, //导出的数据
responseType: "blob"
})
.then(res => {
const link = document.createElement("a");
let blob = new Blob([res.data], { type: "multipary/form-data" });
link.style.display = "none";
link.href = URL.createObjectURL(blob);
link.setAttribute("download", decodeURI(Date.now()+'导出模板.xlsx'));
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
console.log(res);
})
},
后端设置文件名,字段名等,将数据进一步封装.并以文件流的方法返回到前端
public void exportData(@RequestBody List<ClueDTO> clueDTOlist, HttpServletResponse response) {
List<ClueDTO> list = new ArrayList<>();
try {
response.setContentType("application/vnd.ms-excel; charset=utf-8");
response.setCharacterEncoding("utf-8");
String fileName = "模板";
response.setHeader("Content-Disposition", "attachment;filename=" + "导出记录"+ ".xlsx");
log.info(URLEncoder.encode(fileName, "utf-8") + ".xlsx");
EasyExcel.write(response.getOutputStream(), ClueDTO.class).sheet("模板").doWrite(clueDTOlist);
} catch (Exception e) {
log.error("下载报表异常:{}", e.getMessage());
throw new RuntimeException("下载报表异常");
}
}
文件导入导出多种多样, 以上仅是针对Excel文件的导入导出的其中一种方法.后续有需要的话,可将具体Demo上传至github,欢迎在评论区讨论.
xushumin:规则是用来打破的,然后重组,再打破
评论中有人询问到Result这个类,这是自己封装的一个接口返回规范类,是自定义的。类信息如下:
@ApiModel("通用接口返回对象")
@Data
public class Results<T> {
@ApiModelProperty(required = true,notes = "结果码",example = "200")
private int state;
@ApiModelProperty(required = true,notes = "时间戳",example = "1567425139000")
private long time;
@ApiModelProperty(required = true,notes = "返回信息",example = "SUCCESS")
private String message;
@ApiModelProperty(required = true,notes = "返回数据",example = "{\"name\":\"blues\"}")
private T content;
public Results(int code, String msg, T obj){
setState(code);
setMessage(msg);
setContent(obj);
setTime(System.currentTimeMillis());
}
}