本文主要以多张图片打成ZIP包下载为例展开。
以下,是ZIP打包下载的关键编码:
友情说明:ZIP打包下载功能,行文中将其作为一个Service服务对外开放。测试验证的话,可自行创建Controller层,建议使用REST风格API,传入HttpServletResponse对象以及指定特定目录下的图片文件名称数据集(数据类型:List),即可完成测试!
public class CompressServiceImpl {
private static final Logger logger = LoggerFactory.getLogger(CompressServiceImpl.class);
/**
* 下载ZIP格式压缩包
*
* @param imageNames 图片名称列表
* @param response 响应体
*/
public void downloadZipArchive(List<String> imageNames, HttpServletResponse response) {
// 存放图片文件的目录所在路径,需自行调整(绝对路径或者相对路径皆可)
String dirPath = "images/";
try {
OutputStream out = customizeResponse(response, String.valueOf(new Date().getTime()), "zip");
ZipOutputStream zipOut = new ZipOutputStream(out);
for (String imageName : imageNames) {
// 文件夹路径
String filePath = dirPath + imageName;
byte[] data = Files.readAllBytes(new File(filePath).toPath());
Path path = Paths.get(filePath);
// 命名ZIP文件,打包时移除目录所在路径
zipOut.putNextEntry(new ZipEntry(path.toFile().getName()));
customizeOutputStream(zipOut, data, BUFFER_SIZE);
zipOut.closeEntry();
}
zipOut.flush();
zipOut.close();
} catch (IOException e) {
e.printStackTrace();
logger.info("CompressServiceImpl.downloadZipArchive ========= 下载失败: [{}] =========", e.getMessage());
}
}
/**
* 配置response实例
*
* @param response 响应体
* @param fileName 文件名称
* @param fileType 文件类型
* @return OutputStream
* @throws IOException
*/
private OutputStream customizeResponse(HttpServletResponse response, String fileName,
String fileType)
throws IOException {
fileName = new String(fileName.getBytes(), StandardCharsets.UTF_8);
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + "." + fileType);
response.setContentType("multipart/form-data");
return response.getOutputStream();
}
/**
* 读取字节数据,存入输出流outputStream
*
* @param out 输出流
* @param data 希望写入的数据
* @param bufferLength 写入数据是循环读取写入的,此为每次读取的字节长度
* @throws IOException
*/
private void customizeOutputStream(OutputStream out, byte[] data, int bufferLength)
throws IOException {
int readTimes = data.length 0ufferLength;
int count = readTimes == 0 ? data.length / bufferLength : data.length / bufferLength + 1;
for (int countIndex = 0; countIndex < count; countIndex++) {
if (countIndex == count - 1 && readTimes != 0) {
out.write(data, countIndex * bufferLength, readTimes);
continue;
}
out.write(data, countIndex * bufferLength, bufferLength);
}
}
}