将文件夹保留目录打包为 ZIP 压缩包并下载
上周做了一个需求,要求将数据库保存的 html 界面取出后将服务器下的css和js文件一起打包压缩为ZIP文件,返回给前台;在数据库中保存的是html标签,查出后,我把这些内容写入css和js等其他文件所在目录的一个文件内,然后将这整个文件夹压缩打包下载,解决过程中遇到了下载出来后并没有保存层级目录,在查了好久方法后完成了如下版本,已经可以正常下载并保留层级目录。
话不多说,直接上代码,有不足的地方希望大哥们提出来一起探讨
1 //ZIP文件包压缩下载
2 @Override
3 public void downloadZip(String id,HttpServletResponse response) {
4 String zipPath = "你的路径";
5 File file = new File(zipPath,"index.html");//创建指定目录和文件名称的文件对象
6 BufferedWriter bw = null;//创建缓冲流
7 try {
8 //校验文件目录是否存在,文件是否存在
9 chenkFile(file,zipPath);
10 //这一步是我将指定内容从数据库写入文件
11 ModuleInfo moduleInfo = moduleDao.getByModId(id);
12
13 bw = new BufferedWriter(new FileWriter(file));
14 //把内容写入临时文件中
15 bw.write(moduleInfo.getContent());
16 //此处不能删除,要关闭一次 不关闭无法写入内容 导致压缩包内文件无内容
17 bw.flush();
18 bw.close();
19 //将目标文件压缩为ZIP并下载
20 ZipUtil.zip(zipPath,response);
21 //删除文件(防止下一次压缩时有重复文件名)
22 file.delete();
23 } catch (Exception e) {
24 log.error("html压缩"+e.getMessage(),e);
25 }finally {
26 //这是我写的IO流关闭工具类 如需要可以看我关于IO流关闭的文章
27 IOCloseUtils.ioClose(bw);
28 }
29 }
30
31 //判断文件目录和文件是否存在 如否则新建
32 public void chenkFile(File file,String path){
33 try {
34 if (file.exists()){//如果目录存在
35 if (!file.isDirectory()){//如果文件不存在
36 file.createNewFile();//创建文件
37 }
38 }else {//如果目录不存在
39 File file1 = new File(path);//创建指定目录文件对象
40 file1.mkdirs();//创建目录
41 file.createNewFile();//创建文件
42 }
43 } catch (IOException e) {
44 log.error(e.getMessage(),e);
45 }
46 }
public static void zip(String sourceFileName, HttpServletResponse response){
ZipOutputStream out = null;
BufferedOutputStream bos = null;
try {
//将zip以流的形式输出到前台
response.setHeader("content-type", "application/octet-stream");
response.setCharacterEncoding("utf-8");
// 设置浏览器响应头对应的Content-disposition
//参数中 testZip 为压缩包文件名,尾部的.zip 为文件后缀
response.setHeader("Content-disposition",
"attachment;filename=" + new String("testZip".getBytes("gbk"), "iso8859-1")+".zip");
//创建zip输出流
out = new ZipOutputStream(response.getOutputStream());
//创建缓冲输出流
bos = new BufferedOutputStream(out);
File sourceFile = new File(sourceFileName);
//调用压缩函数
compress(out, bos, sourceFile, sourceFile.getName());
out.flush();
log.info("压缩完成");
} catch (Exception e) {
log.error("ZIP压缩异常:"+e.getMessage(),e);
} finally {
IOCloseUtils.ioClose(bos,out);
}
}
public static void compress(ZipOutputStream out, BufferedOutputStream bos, File sourceFile, String base){
FileInputStream fos = null;
BufferedInputStream bis = null;
try {
//如果路径为目录(文件夹)
if (sourceFile.isDirectory()) {
//取出文件夹中的文件(或子文件夹)
File[] flist = sourceFile.listFiles();
if (flist.length == 0) {//如果文件夹为空,则只需在目的地zip文件中写入一个目录进入点
out.putNextEntry(new ZipEntry(base + "/"));
} else {//如果文件夹不为空,则递归调用compress,文件夹中的每一个文件(或文件夹)进行压缩
for (int i = 0; i < flist.length; i++) {
compress(out, bos, flist[i], base + "/" + flist[i].getName());
}
}
} else {//如果不是目录(文件夹),即为文件,则先写入目录进入点,之后将文件写入zip文件中
out.putNextEntry(new ZipEntry(base));
fos = new FileInputStream(sourceFile);
bis = new BufferedInputStream(fos);
int tag;
//将源文件写入到zip文件中
while ((tag = bis.read()) != -1) {
out.write(tag);
}
bis.close();
fos.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
IOCloseUtils.ioClose(bis,fos);
}
}
如图下载后如图所示,名为 testZip.zip 的文件 层级目录都有保留