依赖自己导,先说一下最后实现的效果:前端用户批量选中数据点击导出,后端拿到数据创建并写入到excel表中,并且把图片压缩成ZIP包,成功后浏览器自动下载。
后端代码:
(1) excel代码
@PostMapping("/exportExcel")
public void exportExcel(@RequestBody Map<String,Object> params ,HttpServletResponse response){
try {
//获取需要导出的数据id
List<Integer> xlhs = (List<Integer>) params.get("xlhs");
List<Screenshot> dataList = screenShotService.listByIds(xlhs);
response.setContentType("application/vnd.openxmlformats-officedocument.speadsheetml.sheet");
response.setCharacterEncoding("UTF-8");
// 这里URLEncoder.encode可以防止中文乱码, 与EasyExcel无关
String fileName = URLEncoder.encode("这里是Excel文件名", "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
//不写入Excel中的表字段
Set<String> excludeColumns = new HashSet<>();
excludeColumns.add("id");
excludeColumns.add("src");
EasyExcel.write(response.getOutputStream(), ScreenshotVo.class).excludeColumnFiledNames(excludeColumns).sheet("巡课截图信息").doWrite(dataList);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
(2) 压缩包代码
@PostMapping("/exportZip")
public void exportZip(@RequestBody Map<String,Object> params ,HttpServletResponse response){
//准备需要导出的数据
List<Integer> xlhs = (List<Integer>) params.get("xlhs");
List<Screenshot> dataList = screenShotService.listByIds(xlhs);
//图片链接的前缀
String urlPrefix = String.valueOf(params.get("urlPrefix"));
byte[] buf = new byte[1024];
BufferedOutputStream bos = null;
ZipOutputStream out = null;
try {
// 重置
response.reset();
// 允许http://127.0.0.1:8080进行跨域访问
response.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:8099");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); // 允许的访问方法
response.setHeader("Access-Control-Max-Age", "3600"); // 缓存该结果的时间,单位为秒
response.setHeader("Access-Control-Allow-Headers",
"Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers"); // 允许的自定义请求头
response.setContentType("application/octet-stream");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-disposition","attachment;filename=" + URLEncoder.encode("巡课截图.zip",
"UTF-8"));
bos = new BufferedOutputStream(response.getOutputStream());
out = new ZipOutputStream(bos);
for (Screenshot screenshot:dataList){
String imgUrl = urlPrefix + screenshot.getSrc(); //拼接图片完整路径
//图片重命名
String imgName = screenshot.getJsmc()+"_"+screenshot.getSkbj()+"_"+screenshot.getJtdate()+
imgUrl.substring(imgUrl.lastIndexOf("."));
URL url = new URL(imgUrl);
URLConnection conn = url.openConnection();
InputStream in = conn.getInputStream();
out.putNextEntry(new ZipEntry(imgName));
int len = -1;
while ((len=in.read(buf))!=-1){
out.write(buf,0,len);
}
in.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
if (out!=null)
out.close();
if (bos!=null)
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
前端有两种请求方式都可以实现:
(1) ajax请求下载Excel:
//导出数据
exportData(){
//this.checkList是存放前端选中数据的数组
if (this.checkList.length == 0) {
this.$message.info("请勾选要导出的数据");
return false;
}
var ids = [];
//将每条数据的id取出来封装成数组
for(var i=0;i<this.checkList.length;i++){
ids.push(this.checkList[i].id)
}
var jsonData = {
"ids ": ids
}
var url = "请求路径";
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8'); //必须暴露请求头 不设置后端拿不到数据
xhr.responseType = "blob"; //响应类型必须设为二进制文件流
xhr.onload = function () {
// 请求完成
if (this.status === 200) {
// 返回200
var blob = this.response;
// 从response的headers中获取filename, 后端response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx") 设置的文件名;
var contentDispositionHeader = xhr.getResponseHeader('Content-Disposition');
var filename = decodeURIComponent(contentDispositionHeader.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/)[1]);
// 下载
var reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = function (e) {
var a = document.createElement('a'); //创建a标签
a.download = filename;
a.href = e.target.result;
document.body.appendChild(a); // 将a标签挂载上去
a.click();
document.body.removeChild(a); // 移除a标签
}
}
};
// 发送ajax请求
xhr.send(JSON.stringify(jsonData))
},
(2) vue方法请求下载Excel:
//导出数据
exportData(){
//this.checkList是存放前端选中数据的数组
if (this.checkList.length == 0) {
this.$message.info("请勾选要导出的数据");
return false;
}
var ids = [];
//将每条数据的id取出来封装成数组
for(var i=0;i<this.checkList.length;i++){
ids.push(this.checkList[i].id)
}
var jsonData = {
"ids ": ids
}
exportExcel(jsonData).then(res=>{
// 将文件流转成blob形式
const blob = new Blob([res], { type: 'application/vnd.ms-excel' })
// 创建一个超链接,将文件流赋进去,然后实现这个超链接的单击事件
const eLink = document.createElement('a')
console.log(res.headers);
var contentDispositionHeader = res.headers['content-disposition']
eLink.download = decodeURIComponent(contentDispositionHeader.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/)[1]);
eLink.style.display = 'none'
eLink.href = URL.createObjectURL(blob)
document.body.appendChild(eLink)
eLink.click()
URL.revokeObjectURL(eLink.href) // 释放URL 对象
document.body.removeChild(eLink)
this.$message.success("导出成功")
})
},
(3) ajax请求下载zip压缩包:
/*************************** 下载zip ********************************************/
var zipurl = config.apiUrl+'/ScreenShot/exportZip';
var zipxhr = new XMLHttpRequest();
zipxhr.open('POST', zipurl, true);
zipxhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8'); //必须暴露请求头 不设置后端拿不到前端传的参数
zipxhr.responseType = "blob"; //响应类型必须设为二进制文件流
zipxhr.onload = function () {
// 请求完成
if (this.status === 200) {
// 返回200
var zipblob = this.response;
// 从response的headers中获取filename, 后端response.setHeader("Content-disposition", "attachment;filename="+ URLEncoder.encode("巡课截图.zip", "UTF-8")) 设置的文件名;
// var contentDispositionHeader = zipxhr.getResponseHeader('Content-Disposition');
// console.log(contentDispositionHeader);
// var zipfilename = decodeURIComponent(contentDispositionHeader.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/)[1]);
var zipfilename = "巡课截图.zip";
// 下载
var zipreader = new FileReader();
zipreader.readAsDataURL(zipblob);
zipreader.onload = function (e) {
var zipa = document.createElement('a'); //创建a标签
zipa.download = zipfilename;
zipa.href = e.target.result;
document.body.appendChild(zipa); // 将a标签挂载上去
zipa.click();
document.body.removeChild(zipa); // 移除a标签
}
}
};
// 发送ajax请求
zipxhr.send(JSON.stringify(jsonData));