Java文件压缩成zip,处理base64和url(原生)<一>
将多个文件打包到zip提供给用户下载,抽离出来了一个工具类,支持单文件、多文件、按类型的多文件的压缩和下载。
1.实体类
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* @date 2022/5/25 15:11
* @description:
*/
@Data
public class ZipDto implements Serializable {
/**类型名称/子目录名称*/
private String typeName;
/**文件路径*/
private String fileUrl;
/**
* 分类型时,集合有值
* 文件路径集合
*/
private List<String> urlList;
}
2.工具类
主要方法:
- downZipListType: 允许用户按类型将文件列表打包成zip文件进行下载。
- downZipList: 提供批量下载功能,可以将多个文件一起打包成zip文件。
- downZipOne: 为单个文件提供下载功能,虽然是单个文件,但为了保持统一性,仍然会将其打包成zip格式。
删除了项目敏感import,自行导入实体即可。
import cn.hutool.core.util.StrUtil;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.util.Collections;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* @date 2023/10/18 17:32
* @description:
*/
@Slf4j
@UtilityClass
public class CustomOriZipUtils {
private static final String SUFFIX_ZIP = ".zip";
private static final String UNNAMED = "未命名";
/**
* 按类型批量下载。
*/
public static void downZipListType(List<ZipDto> list, String fileName, HttpServletRequest request, HttpServletResponse response) {
try (ZipOutputStream zos = createZipOutputStream(response, request, fileName)) {
for (ZipDto dto : list) {
writeToZipStream(dto.getUrlList(), zos, dto.getTypeName());
}
} catch (Exception e) {
log.error("创建zip文件出错", e);
}
}
/**
* 批量下载。
*/
public static void downZipList(List<ZipDto> list, String fileName, HttpServletRequest request, HttpServletResponse response) {
try (ZipOutputStream zos = createZipOutputStream(response, request,fileName)) {
for (ZipDto dto : list) {
writeToZipStream(Collections.singletonList(dto.getFileUrl()), zos, dto.getTypeName());
}
} catch (Exception e) {
log.error("创建zip文件出错", e);
}
}
/**
* 下载单个记录。
*/
public void downZipOne(ZipDto dto, String fileName, HttpServletRequest request, HttpServletResponse response) {
try (ZipOutputStream zos = createZipOutputStream(response, request,fileName)) {
writeToZipStream(Collections.singletonList(dto.getFileUrl()), zos, dto.getTypeName());
} catch (Exception e) {
log.error("创建zip文件出错", e);
}
}
/**
* 为下载设置响应。
*/
private void setResponse(HttpServletResponse response, HttpServletRequest request,String fileName) throws UnsupportedEncodingException {
if (StrUtil.isAllBlank(fileName)) {
fileName = LocalDate.now() + UNNAMED;
}
if (!fileName.endsWith(SUFFIX_ZIP)) {
fileName += SUFFIX_ZIP;
}
fileName = encodeFileName(request, fileName);
response.setHeader("Connection", "close");
response.setHeader("Content-Type", "application/octet-stream;charset=UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
}
/**
* 将URL写入zip流中。
*/
private static void writeToZipStream(List<String> urls, ZipOutputStream zos, String subDir) {
byte[] buffer = new byte[1024];
for (String url : urls) {
if (StrUtil.isNotBlank(url)) {
try (InputStream is = new URL(url).openStream()) {
String fileName = StrUtil.isAllBlank(subDir) ? getFileName(url) : subDir + "/" + getFileName(url);
zos.putNextEntry(new ZipEntry(fileName));
int length;
while ((length = is.read(buffer)) > 0) {
zos.write(buffer, 0, length);
}
zos.closeEntry();
} catch (Exception e) {
log.error("将文件 [{}] 写入zip时出错", url, e);
}
}
}
}
/**
* 根据浏览器类型编码文件名。
*/
private static String encodeFileName(HttpServletRequest request, String fileName) throws UnsupportedEncodingException {
String userAgent = request.getHeader("USER-AGENT");
if (userAgent.contains("Firefox")) {
return new String(fileName.getBytes(), "ISO8859-1");
}
return URLEncoder.encode(fileName, "UTF-8");
}
/**
* 创建ZipOutputStream并设置响应头。
*/
private static ZipOutputStream createZipOutputStream(HttpServletResponse response,HttpServletRequest request, String fileName) throws IOException {
setResponse(response, request,fileName);
return new ZipOutputStream(response.getOutputStream());
}
/**
* 从url获取文件名
* @param url
* @return
*/
public String getFileName(String url) {
return url.substring(url.lastIndexOf('/') + 1);
}
3.效果
多目录文件压缩下载:
单文件打包下载:
万物皆有裂缝,那是光照进来的地方 – 莱昂纳德·科恩