后端
controller
public void downloadFiles(@RequestBody @Valid Req<DownloadFilesDto> requestDTO, HttpServletResponse response) throws Exception {
byte[] zipBytes = prpmUploadImageService.downloadFiles(requestDTO.getData());
String filename = requestDTO.getData().getCaseNo() +"_"+ requestDTO.getData().getLossId()+".zip";
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
StringBuilder contentDispositionValue = new StringBuilder();
contentDispositionValue.append("attachment; filename=")
.append(filename)
.append(";")
.append("filename*=")
.append("utf-8''")
.append(filename);
response.setHeader("Access-Control-Expose-Headers","filename");
response.setHeader("Content-disposition", contentDispositionValue.toString());
response.setHeader("filename",filename);
IoUtil.write(response.getOutputStream(),true,zipBytes);
}
service
byte[] downloadFiles(DownloadFilesDto downloadFilesDto) throws Exception;
serviceImpl
@Override
public byte[] downloadFiles(DownloadFilesDto downloadFilesDto) throws Exception {
try {
//模拟从数据库查出多张图片路径
String[] urlArr = new String[]{
"图片链接1",
"图片链接2"
};
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ZipOutputStream zip = new ZipOutputStream(outputStream);
Map<String,Integer> repeatMap = new ConcurrentHashMap<>();
for (String url : urlArr) {
//下载查出的图片
String path = IdUtils.randomUUID()+".png";
byte[] bytes = IOUtils.toByteArray(new URL(url));
ZipUtils.append(zip,bytes, path,repeatMap);
}
IOUtils.closeQuietly(zip);
byte[] zipBytes = outputStream.toByteArray();
return zipBytes;
} catch (IOException e) {
e.printStackTrace();
}
}
工具类
package org.apache.commons.io.IOUtils
package cn.hutool.core.io.IoUtil
@Slf4j
public class ZipUtils extends ZipUtil {
@SneakyThrows
public static void append(ZipOutputStream zip, byte[] bytes, String path){
zip.putNextEntry(new ZipEntry(path));
IOUtils.write(bytes, zip);
}
@SneakyThrows
public static void append(ZipOutputStream zip, byte[] bytes, String path, @NotNull Map<String,Integer> repeatMap){
if(repeatMap == null){
repeatMap = new ConcurrentHashMap<>();
}
if(repeatMap.containsKey(path)){
String fileName = FileUtil.getName(path);
log.info("重复文件,路径:{},文件名:{},重新命名",path,fileName);
Integer index = repeatMap.get(path);
index = (index == null?0:index) + 1;
repeatMap.put(path,index);
String namePrefix = FileUtil.getPrefix(fileName);
String nameSuffix = FileUtil.getSuffix(fileName);
fileName = namePrefix + "(" + index +")." +nameSuffix;
path = path(path) + fileName;
log.info("重复文件重新命名后,路径:{},文件名:{}",path,fileName);
repeatMap.put(path,0);
}else{
repeatMap.put(path,0);
}
zip.putNextEntry(new ZipEntry(path));
IOUtils.write(bytes, zip);
}
public static String path(String fileName) {
if (null == fileName) {
return null;
} else {
int len = fileName.length();
if (0 == len) {
return fileName;
} else {
if (CharUtil.isFileSeparator(fileName.charAt(len - 1))) {
--len;
}
int begin = 0;
int end = len;
String prefix = FileUtil.getName(fileName);
return fileName.substring(begin, end - prefix.length());
}
}
}
}
前端
js部分
引入后端接口
export function download(data) {
return request({
url: '/survey/image/downloadFiles',
method: 'post',
data: data,
responseType: 'blob'
})
}
方法调用接口
downloadFile(){
download(obj).then((res)=>{
const binaryData = []
binaryData.push(res)// res 后台返回的流数据
this.url = window.URL.createObjectURL(new Blob(binaryData, { type: 'application/zip;charset-UTF-8' }))
window.open(this.url)
})
},