Controller层
@ApiOperation(value = "批量下载素材")
@GetMapping("/batchDownload")
public void batchDownload(HttpServletResponse response,String ids) throws IOException {
// 这里是让前端传给我文件id 中间以逗号隔开
String[] idsstr = ids.split(",");
// 创建一个list 用来存放文件的路径 我这个是因为同事数据库格式写的有些出入,所以这样转换的,你们自行获取文件路径
List<String> paths = new ArrayList<>();
List<Material> list = materialService.lambdaQuery().in(Material::getId, idsstr).list();
for (Material material : list) {
String path = material.getPath();
String imgFileNameWithPath = wangeditorUploadUrlfile + path.substring(0, 32) + "." + path.substring(32, path.length());
paths.add(imgFileNameWithPath);
}
materialService.batchDownload(response, paths);
}
ServiceImpl
public void batchDownload(HttpServletResponse response,List<String> paths) throws IOException {
if (paths != null) {
// 这里是我创建的一个zip压缩包 wangeditorUploadUrlfile 这个是我创建的一个路径在上面定义了,你们自行定义文件路径
String zipFilePath = wangeditorUploadUrlfile+"临时压缩包.zip";
// 压缩输出流,包装流,将临时文件输出流包装成压缩流,将所有文件输出到这里,打成zip包
ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFilePath));
// 循环调用压缩文件方法,将一个一个需要下载的文件打入压缩文件包
for (String path : paths) {
fileToZip(path, zipOut);
}
// 压缩完成后,关闭压缩流
zipOut.close();
//拼接下载默认名称并转为ISO-8859-1格式
String fileName = new String(("批量下载素材.zip").getBytes(),"ISO-8859-1");
response.setHeader("Content-Disposition", "attchment;filename="+fileName);
//该流不可以手动关闭,手动关闭下载会出问题,下载完成后会自动关闭
ServletOutputStream outputStream = response.getOutputStream();
FileInputStream inputStream = new FileInputStream(zipFilePath);
IOUtils.copy(inputStream, outputStream);
// 关闭输入流
inputStream.close();
//下载完成之后,删掉这个zip包
File fileTempZip = new File(zipFilePath);
fileTempZip.delete();
}
}
// 这个方法其实我也不懂啥意思 都是百度搜到的 ,你们可以自行理解 我不李姐(理解)
public static void fileToZip(String filePath,ZipOutputStream zipOut) throws IOException {
// 需要压缩的文件
File file = new File(filePath);
// 获取文件名称,如果有特殊命名需求,可以将参数列表拓展,传fileName
String fileName = file.getName();
FileInputStream fileInput = new FileInputStream(filePath);
// 缓冲
byte[] bufferArea = new byte[1024 * 10];
BufferedInputStream bufferStream = new BufferedInputStream(fileInput, 1024 * 10);
// 将当前文件作为一个zip实体写入压缩流,fileName代表压缩文件中的文件名称
zipOut.putNextEntry(new ZipEntry(fileName));
int length = 0;
// 最常规IO操作,不必紧张
while ((length = bufferStream.read(bufferArea, 0, 1024 * 10)) != -1) {
zipOut.write(bufferArea, 0, length);
}
//关闭流
fileInput.close();
// 需要注意的是缓冲流必须要关闭流,否则输出无效
bufferStream.close();
// 压缩流不必关闭,使用完后再关
}
总结:
这个大概的思路就是 我先创建一个zip,然后把获取到文件都先放到这个文件里,然后最后关键的一步是 IOUtils.copy(inputStream, outputStream); (其实就是拷贝然后下载),这一步我也不太懂,以后有机会在学习一下,如果有人懂可以教教我。