pom引入zip4j的包
<zip4j.version>2.11.1</zip4j.version>
<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
<version>${zip4j.version}</version>
</dependency>
两种写法,一种是传统写法
@GetMapping(value = {"/companyFileExportZip/{companyId}"})
@ApiOperation("丰台-演出团队附件批量导出")
public void companyFileExportZip(@PathVariable String companyId, HttpServletResponse response) {
log.info("companyFileExportZip companyId is {}", companyId);
// 声明需要手动关闭的流变量(提升作用域)
ZipOutputStream zipOut = null;
BufferedOutputStream bufferedOut = null;
try {
CompanyBean companyBean = performTeamService.getById(companyId);
response.setContentType("application/zip");
// 处理文件名中文编码(可选优化:避免文件名乱码)
String fileName = new String((companyBean.getCompanyName() + ".zip").getBytes("UTF-8"), "ISO-8859-1");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
List<FileBean> fileBeanList = fileService.getFileBeanByBizId(companyId);
String domainName = obsProperties.getDomainName();
// 初始化输出流(替代try-with-resources)
bufferedOut = new BufferedOutputStream(response.getOutputStream());
zipOut = new ZipOutputStream(bufferedOut);
for (int i = 0; i < fileBeanList.size(); i++) {
FileBean fileBean = fileBeanList.get(i);
String fileRealName = fileBean.getFileName();
String fileUrl = fileBean.getFileUrl();
String objKey = fileUrl.substring(domainName.length());
log.info("companyFileExportZip fileName is {},objKey is {}", fileRealName, objKey);
GetObjectRequest request = new GetObjectRequest(obsProperties.getBucketName(), objKey);
ObsObject obsObject = obsClient.getObject(request);
ZipEntry zipEntry = new ZipEntry(fileRealName);
zipOut.putNextEntry(zipEntry);
// 处理单个文件的输入流(手动关闭)
InputStream fileIn = null;
try {
fileIn = obsObject.getObjectContent();
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = fileIn.read(buffer)) != -1) {
zipOut.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
log.error("读取OBS文件流失败,文件名:{}", fileRealName, e);
throw e; // 抛出异常,让外层捕获统一处理
} finally {
// 手动关闭单个文件的输入流
if (fileIn != null) {
try {
fileIn.close();
} catch (IOException e) {
log.warn("关闭OBS文件输入流失败,文件名:{}", fileRealName, e);
}
}
}
zipOut.closeEntry();
}
zipOut.finish();
log.info("companyFileExportZip companyId is {} success", companyId);
} catch (IOException e) {
log.error("文件压缩下载失败,companyId:{}", companyId, e);
// 确保响应状态码设置生效(避免流已提交的异常)
if (!response.isCommitted()) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
} finally {
// 统一关闭外层的ZipOutputStream和BufferedOutputStream
// 关闭顺序:先关包装流(zipOut),再关底层流(bufferedOut)
if (zipOut != null) {
try {
zipOut.close();
} catch (IOException e) {
log.warn("关闭ZipOutputStream失败", e);
}
}
if (bufferedOut != null) {
try {
bufferedOut.close();
} catch (IOException e) {
log.warn("关闭BufferedOutputStream失败", e);
}
}
}
}
一种是简便写法
@GetMapping(value = {"/companyFileExportZip/{companyId}"})
@ApiOperation("丰台文旅-演出团队附件批量导出")
public void companyFileExportZip(@PathVariable String companyId,HttpServletResponse response) {
log.info("companyFileExportZip companyId is {}",companyId);
CompanyBean companyBean = performTeamService.getById(companyId);
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename="+companyBean.getCompanyName()+".zip");
try {
List<FileBean> fileBeanList = fileService.getFileBeanByBizId(companyId);
String domainName = obsProperties.getDomainName();
try (ZipOutputStream zipOut = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()))) {
for (int i = 0 ;i < fileBeanList.size();i++) {
FileBean fileBean = fileBeanList.get(i);
String fileName = fileBean.getFileName();
String fileUrl = fileBean.getFileUrl();
String objKey = fileUrl.substring(domainName.length());
log.info("companyFileExportZip fileName is {},objKey is {}",fileName,objKey);
GetObjectRequest request = new GetObjectRequest(obsProperties.getBucketName(), objKey);
ObsObject obsObject = obsClient.getObject(request);
ZipEntry zipEntry = new ZipEntry(fileName);
zipOut.putNextEntry(zipEntry);
try (InputStream fileIn = obsObject.getObjectContent()) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = fileIn.read(buffer)) != -1) {
zipOut.write(buffer, 0, bytesRead);
}
}
zipOut.closeEntry();
}
zipOut.finish();
}
log.info("companyFileExportZip companyId is {} success",companyId);
} catch (IOException e) {
log.error("文件压缩下载失败", e);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
两种写法,主要起别在try、catch的使用上。这两种写法,都支持下载的压缩文件中包含压缩文件的情况