需求:下载文件过多,需要点击每个文件进行下载,比较繁琐
优化:在后台将多个文件打包成zip传给前端
文件下载前端处理 请看我的另一篇文章
easyexcel的导入和导出
主要写后端的zip打包,以及中间文件的处理
@ResponseBody
@PostMapping("/batchDown")
public void batchDown(@RequestBody JSONObject jsonObject, HttpServletRequest request, HttpServletResponse response) throws IOException {
try {
// 获取待下载的文件配置参数集合
JSONArray fileList = jsonObject.getJSONArray("fileList");
List<String> idList = JSON.parseArray(fileList.toJSONString(), String.class);
List<HashMap> objList = xxxService.getFileList(idList);
String rootPath = "F:\\file";
//待压缩的文件夹路径
String path = rootPath + "\\detail";
File[] fileArr = getFileObj(path, objList);
//将对应文件夹下的文件进行打包,后删除明细文件夹下所有文件
String zipFileName = "XXX.zip";//定义zip文件的名称
String zipPath = rootPath+ "\\" + zipFileName;// zip包存放路径
ZipUtil.compressFilesToZip(path,zipPath,fileArr,response);
} catch (Exception e) {
e.printStackTrace();
// 重置response
response.reset();
response.setContentType("application/json;charset=utf-8");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Origin", HttpContextUtils.getOrigin());
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.getWriter().write(JsonUtils.toJson(R.error("下载异常")));
}
}
/**
* 获取待压缩文件列表,生成后存放在明细文件夹下
* @param path 待压缩的文件夹路径
* @param objList 生成文件的依据参数
* @return
* @throws Exception
*/
private File[] getFileObj(String path, List<HashMap> objList) throws Exception {
//创建明细文件夹
File file = new File(path);
if(!file.exists()){//不存在创建新的文件夹
Files.createDirectory(Paths.get(path));// 这个方法可以一并创建不存在的父目录
}else{//存在先删除后创建
ZipUtil.deleteFolders(path);
Files.createDirectory(Paths.get(path));
}
//根据params的不同配置,从数据库获取各自的数据
for (HashMap params : objList) {
//创建文件
File fileObj = null;
try {
String fileName = params.get("fileName").toString();
fileObj = new File(path + "\\" + fileName);
} catch (Exception e) {
log.error("文件生成失败,文件名异常.异常信息:{}", e.getMessage());
throw new Exception("文件生成失败,文件名异常");
}
//data() 根据params不同获取不同的数据
EasyExcel.write(fileObj, Entity.class)
.sheet("XXX")
.doWrite(data(params));//此处的data()根据具体的业务需求编写
}
return file.listFiles();// 获取明细文件夹下的文件列表
}
zip工具类
多个文件打包成zip下载
import lombok.extern.slf4j.Slf4j;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* 多个文件打包zip下载
*/
@Slf4j
public class ZipUtil {
public static void compressFilesToZip(String path, String zipPath, File[] files, HttpServletResponse response) throws IOException {
compressFilesToZipNot(path,zipPath,files,response,true);
}
public static void compressFilesToZip(String path, String zipPath, File[] files, HttpServletResponse response,boolean isDelete) throws IOException {
compressFilesToZipNot(path,zipPath,files,response,isDelete);
}
/**
* @param path 待压缩目录
* @param zipPath 压缩文件路径
* @param files 被压缩文件列表
* @param response 响应流
* @param isDelete 是否删除明细文件
* @throws IOException
*/
public static void compressFilesToZipNot(String path, String zipPath, File[] files, HttpServletResponse response,boolean isDelete) throws IOException {
// 创建临时zip文件
File zipFile = new File(zipPath);
// 将文件添加到zip中
addToZip(files, zipFile);
//向前端写入
try ( FileInputStream fis = new FileInputStream(zipFile);
ServletOutputStream outputStream = response.getOutputStream()) {
//获取zip文件名
int lastIndexOf = zipPath.lastIndexOf("\\");
String zipFileName = zipPath.substring(lastIndexOf + 1);
response.setHeader("Cache-Control", "max-age=" + 100);
response.setContentType("application/x-download");
response.setHeader("windows-Target", "_blank");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Origin", HttpContextUtils.getOrigin());
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.setHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(zipFileName, "UTF-8"));
// 将zip文件写入输出流
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
} finally {
// 删除临时zip文件
// zipFile.delete();
if(isDelete){
deleteFolders(path);
log.info("中间文件删除成功");
}
}
}
/**
* @param files 文件集合
* @param zipFile 压缩文件
* @throws IOException
*/
private static void addToZip(File[] files, File zipFile) throws IOException {
try (FileOutputStream fos = new FileOutputStream(zipFile);
ZipOutputStream zos = new ZipOutputStream(fos);
) {
for (File file : files) {
if (file.isFile()) {
ZipEntry entry = new ZipEntry(file.getName());
zos.putNextEntry(entry);
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))){
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = bis.read(buffer)) != -1) {
zos.write(buffer, 0, bytesRead);
}
zos.closeEntry();
}
}
}
}
}
/**
* 删除指定文件夹下文件
*
* @param filePath
*/
public static void deleteFolders(String filePath) throws IOException {
Path path = Paths.get(filePath);
try {
Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException {
Files.delete(file);
log.debug("删除文件: {}", file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir,
IOException exc) throws IOException {
Files.delete(dir);
log.debug("文件夹被删除: {}", dir);
return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
e.printStackTrace();
throw new IOException("文件夹删除失败");
}
}
}