前端代码
//批量下载
async function 自己在这起一个方法名 {
let downloadFilesListRes = await downloadFilesList(selectedRowKeys.value);
//res为接口所返回的文件流
var blob = new Blob([downloadFilesListRes], { type: 'application/octet-stream;charset=UTF-8' });
//新窗口打开
var link = document.createElement('a');
link.style.display = 'none';
link.href = window.URL.createObjectURL(blob);
link.download = 'files.zip'; //浏览器下载的名字
link.target = '_blank';
link.click();
window.URL.revokeObjectURL(link.href); //释放掉blob对象
}
向后台发起请求
export const downloadFilesList = (params) => {
return defHttp.post({ url:'后端接口路径', responseType: 'blob', params }, { isTransformResponse: false });
};
后台代码
@RestController
@RequestMapping(value = "自己的路径")
public class 类名 {
/**
* 批量文件下载
*/
@SneakyThrows
@PostMapping("路径")
public void 方法名(@RequestBody ArrayList<String> fileIdList, HttpServletResponse response) {
//设置返回响应头
response.reset();
//判断文件id是否为空
if (CollectionUtils.isEmpty(fileIdList)) {
throw new JeecgBootException("未找到任何文件");
}
//查出这些文件的所有信息
List<PrjProjectFile> fileInfoList = prjProjectFileService.list(
new LambdaQueryWrapper<PrjProjectFile>().in(PrjProjectFile::getId, fileIdList)
);
//调用单个文件的下载接口 拿到所有文件的流数组
InputStream[] inputStreams = fileInfoList.stream().filter(info -> StringUtil.isNotEmpty(info.getFilePath())).map(info -> this.fileService.download(info.getFilePath())).toArray(InputStream[]::new);
//拿到所有文件名字的数组 因为名字可能重复我拼接了一个时间戳
String[] strings = fileInfoList.stream().filter(info -> StringUtil.isNotEmpty(info.getFilePath())).map(info ->info.getCreateTime().toString()+info.getFileName()).toArray(String[]::new);
//调用Hutool 工具的压缩方法
ZipUtil.zip(response.getOutputStream(), strings, inputStreams);
}
}
/** * 将文件流压缩到目标流中 * * @param out 目标流,压缩完成自动关闭 * @param paths 流数据在压缩文件中的路径或文件名 * @param ins 要压缩的源,添加完成后自动关闭流 * @since 5.5.2 */ public static void zip(OutputStream out, String[] paths, InputStream[] ins) { zip(getZipOutputStream(out, DEFAULT_CHARSET), paths, ins); }
我用的压缩工具里的这个方法 , 不用去找缓存的地方了