在实际开发项目过程中,文件下载是异常频繁的操作,但是多文件zip打包下载并非常见使用场景,本文介绍如何使用io流操作多文件实现压缩并下载。
特别说明:
无需依赖任何第三方包或者拆件
一、效果展示:
1.打包前文件列表展示
2.打包下载展示
二、关键代码实现方案
@ApiOperation("测试多文件压缩打包并下载")
@PostMapping("/{devIds}/getMultipleFilesPackAndDownload")
public void getMultipleFilesPackAndDownload(@PathVariable("devIds") String devIds,
HttpServletResponse response) {
//业务数据用于查询文件列表
if (!StringUtils.isBlank(devIds)) {
ByteArrayOutputStream byteArrayOutputStream = null;
OutputStream responseOutputStream = null;
try {
//测试方法从classpath下读取
File folder = new File(this.getClass().getResource("/test01/").getPath());
File[] files = folder.listFiles();
if (files != null || files.length > 0) {
byteArrayOutputStream = new ByteArrayOutputStream();
ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream);
// 解决文件名重复报错
ArrayList<String> repeatFileName = new ArrayList<>();
FileInputStream fis = null;
String fileName = null;
ZipEntry zipEntry = null;
// 遍历文件列表,将每个文件添加到压缩包中
for (File f : files) {
fis = new FileInputStream(f);
fileName = f.getName();
zipEntry = new ZipEntry(fileName);
zipOutputStream.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while((length = fis.read(bytes)) >= 0) {
zipOutputStream.write(bytes, 0, length);
}
// 检查名称是否已经存在,为防止报错相同名称文件名称后面跟上数字
if (repeatFileName.contains(fileName)) {
long count = repeatFileName.stream().filter(str -> str.startsWith(f.getName())).count();
fileName = fileName.split("\\.")[0] + count+fileName.split("\\.")[1];
}else{
fileName = fileName;
}
repeatFileName.add(fileName);
fis.close();
}
// 结束打包
zipOutputStream.closeEntry();
zipOutputStream.close();
// 返回压缩包给前端
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=test2411.zip");
response.setContentType("application/zip");
byte[] bytes = byteArrayOutputStream.toByteArray();
responseOutputStream = response.getOutputStream();
responseOutputStream.write(bytes);
responseOutputStream.flush();
} else {
throw new DataException("请求出错,未查询到数据");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (!Objects.isNull(responseOutputStream)) {
responseOutputStream.close();
}
if (!Objects.isNull(byteArrayOutputStream)) {
byteArrayOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
} else {
throw new DataException("请求出错,请选择业务数据");
}
}