springboot将多个文件压缩成zip流并通过ResponseEntity下载-不用将zip保存硬盘
场景:之前遇到需要请求多个文件同时返回的问题,想到用zip压缩后返回的办法,但是奈何网上全都是先保存硬盘,在返回文件流,或者nginx代理下载文件的方式,亦或者是用其他种方式,反正最终都没有满意的。
- 以下是通过使用springboot的ResponseEntity来直接返回字节码的方式,将多个文件压缩人zip流,然后转换成字节返回。
上代码
1、ZipUtils工具类
public class ZipUtils {
/**
* 文件批量压缩,不保存实际位置
*
* @param byteList 文件字节码Map,k:fileName,v:byte[]
* @param byteOutPutStream 字节输出流
*/
public static void batchFileToZIP(Map<String, byte[]> byteList, ByteArrayOutputStream byteOutPutStream) {
ZipOutputStream zipOutputStream = new ZipOutputStream(byteOutPutStream);
try {
for (Map.Entry<String, byte[]> entry : byteList.entrySet()) {
//写入一个条目,我们需要给这个条目起个名字,相当于起一个文件名称
zipOutputStream.putNextEntry(new ZipEntry(entry.getKey()));
zipOutputStream.write(entry.getValue());
}
zipOutputStream.closeEntry();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
zipOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2、ResponseEntity封装工具类
public class ResponseEntityUtils {
/**
* ResponseEntity下载zip文件
*
* @param fileName 文件名
* @param byteFile 字节码
* @param response response
* @return
*/
public static ResponseEntity<byte[]> buildByteFileResponse(String fileName, byte[] byteFile, HttpServletResponse response) {
try {
fileName = URLEncoder.encode(fileName, "UTF-8");
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
response.flushBuffer();
return ResponseEntity.ok().body(byteFile);
} catch (Exception e) {
LOGGER.warn("Warning", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("下载失败.".getBytes());
}
}
}
3、使用方法(可以当做controller)
Map<String, byte[]> byteFileMap = new HashMap<>();
byteFileMap.put(“testfile.txt”, "我是文件内容".getBytes());
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ZipUtils.batchFileToZIP(byteFileMap, byteArrayOutputStream);
String zipFileName = String.format("%s%s", LocalDateTime.now(), ".zip");
HttpServletResponse response = new HttpServletResponse();
return ResponseEntityUtils.buildByteFileResponse(zipFileName, byteArrayOutputStream.toByteArray(), response);
- 以上就是整个调用过程
感谢大佬的文章给的启发,参考了文章后进行了提炼。
附上大佬文章:https://blog.csdn.net/u013521220/article/details/102621784