业务场景:系统有一个数据列表,用户点击某行下载按钮,系统可以将该行数据转化成WORD文档的形式供用户下载查看,这里直接用 XWPFTemplate 可以轻松实现,但是数据太多的情况下用户不可能每条数据都点击下载,不仅耗时而且会在浏览器下载非常多的文件,用户不好整理,体验感较差,于是有了新需求:用户可以多选数据行,然后系统压缩成一个ZIP包,所有文件都在ZIP包里,用户只需要下载一个ZIP即可。
简而言之,就是通过ZIP压缩包的形式实现批量下载
代码实现(只贴了核心代码):
1. 封装方法
public byte[] zipFile(List<DownloadFileDto> downloadFileDtoList) throws Exception {
// 将字节写到一个字节输出流里
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (ZipOutputStream out = new ZipOutputStream(baos)) {
// 创建zip file in memory
for (DownloadFileDto downloadFileDto : downloadFileDtoList) {
ZipEntry entry = new ZipEntry(downloadFileDto.getFileName());
entry.setSize(downloadFileDto.getByteDataArr().length);
out.putNextEntry(entry);
out.write(downloadFileDto.getByteDataArr());
out.closeEntry();
}
} catch (IOException e) {
logger.error("压缩zip数据出现异常", e);
throw new RuntimeException("压缩zip包出现异常");
}
return baos.toByteArray();
}2. 封装DTO
/**
* @author YuePeng
* @date 2022/12/22 11:52
* 存放文件字节流和文件名
*/
public class DownloadFileDto implements Serializable {
private static final long serialVersionUID = 2648469408255550980L;
// 存放文件名
private String fileName = "";
// 存放文件字节流
private byte[] byteDataArr = new byte[0];
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public byte[] getByteDataArr() {
return byteDataArr;
}
public void setByteDataArr(byte[] byteDataArr) {
this.byteDataArr = byteDataArr;
}
@Override
public String toString() {
return "DownloadFileDto{" +
"fileName='" + fileName + '\'' +
", byteDataArr=" + Arrays.toString(byteDataArr) +
'}';
}
}3. Controller层
@ApiOperation(value = "批量下载", notes = "下载ZIP压缩包")
@RequestMapping(value = "/downloadZip", method = RequestMethod.GET)
public ResponseEntity downloadZip(
@RequestParam List<String> ids, HttpServletResponse response) throws Exception {
// ids即为前端传过来的的行数据id集合
if (ids.isEmpty()) {
return new ResponseEntity(HttpStatus.OK);
}
List<DownloadFileDto> downloadFileDtoList = new ArrayList<>();
// 这里的i的作用是保证文件名唯一,否则往ZIP中添加文件会报异常
int i = 1;
for (String id : ids) {
// 你的每一个文件字节流
byte[] bytes = phvEquipReportService.downloadProveTable(id);
String fileName = i + ".docx";
DownloadFileDto dto = new DownloadFileDto();
dto.setFileName(fileName);
dto.setByteDataArr(bytes);
downloadFileDtoList.add(dto);
i++;
}
// FIXME 文件名最好为英文,中文的话下载的文件名会乱码,暂时未解决
String fileName = "download.zip";
response.reset();
response.setCharacterEncoding("UTF-8");
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes(StandardCharsets.UTF_8), "ISO8859-1"));
byte[] dataByteArr = new byte[0];
if (CollectionUtils.isNotEmpty(downloadFileDtoList)) {
try {
dataByteArr = zipFile(downloadFileDtoList);
response.getOutputStream().write(dataByteArr);
response.flushBuffer();
} catch (Exception e) {
logger.error("压缩zip数据出现异常", e);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
}
return new ResponseEntity(dataByteArr, HttpStatus.OK);
}版权声明:本文为MakkaPakka_原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。