将多个地址文件打zip压缩包下载,地址格式可为http、windows、linux,支持zip内创建多级文件夹,同级目录下相同名称文件自动拼接数字后缀。
1、使用示例
@GetMapping("/zip")
public void zip(HttpServletResponse response) throws IOException {
List<ZipUtils.Path> list = Arrays.asList(
new ZipUtils.Path("https://pss.bdstatic.com/static/superman/img/topnav/newxueshuicon-a5314d5c83.png", "文件夹/图片.jpg"),
new ZipUtils.Path("C:\\Users\\aa\\Desktop\\pic.jpg", null),
new ZipUtils.Path("C:\\Users\\aa\\Desktop\\pic.jpg", null)
);
ZipUtils.zip(response, list, "文件.zip");
}

2、代码
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@Slf4j
public class ZipUtils {
public static void zip(HttpServletResponse response, List<Path> fileList, String filename) throws IOException {
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
try (ServletOutputStream os = response.getOutputStream(); ZipOutputStream zos = new ZipOutputStream(os)) {
Set<String> existsFiles = new HashSet<>();
for (Path data : fileList) {
if (StrUtil.isEmpty(data.getUrl())) {
continue;
}
try {
String fileName = getFileName(data.getUrl(), data.getFileName(), existsFiles);
if (data.getUrl().startsWith("http")) {
zipNetwork(zos, data.getUrl(), fileName);
} else {
zipLocal(zos, data.getUrl(), fileName);
}
} catch (Exception e) {
log.error("文件压缩错误:" + data.getUrl(), e);
}
}
}
}
private static String getFileName(String url, String fileName, Set<String> existsFiles) {
if (StrUtil.isEmpty(fileName)) {
String separator = url.startsWith("http") ? "/" : File.separator;
fileName = StrUtil.subAfter(url, separator, true);
}
int i = 1;
String before = StrUtil.subBefore(fileName, ".", true);
String after = StrUtil.subAfter(fileName, ".", true);
while (existsFiles.contains(fileName)) {
fileName = before + "(" + i + ")." + after;
i++;
}
existsFiles.add(fileName);
return fileName;
}
private static void zipNetwork(ZipOutputStream zos, String url, String fileName) throws IOException {
try (BufferedInputStream bis = new BufferedInputStream(new URL(url).openStream())) {
zos.putNextEntry(new ZipEntry(fileName));
IoUtil.copy(bis, zos);
zos.closeEntry();
}
}
private static void zipLocal(ZipOutputStream zos, String url, String fileName) throws IOException {
File file = new File(url);
if (file.exists() && file.isFile()) {
try (BufferedInputStream bis = new BufferedInputStream(Files.newInputStream(file.toPath()))) {
zos.putNextEntry(new ZipEntry(fileName));
IoUtil.copy(bis, zos);
zos.closeEntry();
}
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Path {
/**
* 网络或本地文件路径
* 例:https://pss.bdstatic.com/static/superman/img/topnav/newxueshuicon-a5314d5c83.png
* 例:/Users/root/Documents/abc.JPG
* 例:C:\Users\admin\Desktop\abc.xlsx
*/
private String url;
/**
* 压缩包内文件名,可拼接文件夹,为空时自动截取url后缀
* 例:文件夹/abc.JPG
* 例:abc.JPG
*/
private String fileName;
}
}
1957

被折叠的 条评论
为什么被折叠?



