感谢“zlex.dongliang@gmail.com”。主要代码如下:
1 import java.io.BufferedInputStream; 2 import java.io.File; 3 import java.io.FileInputStream; 4 import java.io.FileOutputStream; 5 import java.io.InputStream; 6 import java.util.Enumeration; 7 import java.util.zip.CRC32; 8 import java.util.zip.CheckedOutputStream; 9 import java.util.zip.ZipEntry; 10 import java.util.zip.ZipFile; 11 import java.util.zip.ZipOutputStream; 12 13 /** 14 * ZIP压缩工具 15 * 16 * @author <a href="mailto:zlex.dongliang@gmail.com">梁栋</a> 17 * @since 1.0 18 */ 19 public class ZipUtils { 20 21 public static final String EXT = ".zip"; 22 private static final String BASE_DIR = ""; 23 24 // 符号"/"用来作为目录标识判断符 25 private static final String PATH = "/"; 26 private static final int BUFFER = 1024; 27 28 /** 29 * 压缩 30 * 31 * @param srcFile 32 * @throws Exception 33 */ 34 public static void compress(File srcFile) throws Exception { 35 String name = srcFile.getName(); 36 String basePath = srcFile.getParent(); 37 String destPath = basePath + name + EXT; 38 compress(srcFile, destPath); 39 } 40 41 /** 42 * 压缩 43 * 44 * @param srcFile 45 * 源路径 46 * @param destPath 47 * 目标路径 48 * @throws Exception 49 */ 50 public static void compress(File srcFile, File destFile) throws Exception { 51 52 // 对输出文件做CRC32校验 53 CheckedOutputStream cos = new CheckedOutputStream(new FileOutputStream(destFile), new CRC32()); 54 55 ZipOutputStream zos = new ZipOutputStream(cos); 56 57 compress(srcFile, zos, BASE_DIR); 58 59 zos.flush(); 60 zos.close(); 61 } 62 63 /** 64 * 压缩文件 65 * 66 * @param srcFile 67 * @param destPath 68 * @throws Exception 69 */ 70 public static void compress(File srcFile, String destPath) throws Exception { 71 compress(srcFile, new File(destPath)); 72 } 73 74 /** 75 * 压缩 76 * 77 * @param srcFile 78 * 源路径 79 * @param zos 80 * ZipOutputStream 81 * @param basePath 82 * 压缩包内相对路径 83 * @throws Exception 84 */ 85 private static void compress(File srcFile, ZipOutputStream zos, String basePath) throws Exception { 86 if (srcFile.isDirectory()) { 87 compressDir(srcFile, zos, basePath); 88 } else { 89 compressFile(srcFile, zos, basePath); 90 } 91 } 92 93 /** 94 * 压缩 95 * 96 * @param srcPath 97 * @throws Exception 98 */ 99 public static void compress(String srcPath) throws Exception { 100 File srcFile = new File(srcPath); 101 102 compress(srcFile); 103 } 104 105 /** 106 * 文件压缩 107 * 108 * @param srcPath 109 * 源文件路径 110 * @param destPath 111 * 目标文件路径 112 * 113 */ 114 public static void compress(String srcPath, String destPath) throws Exception { 115 File srcFile = new File(srcPath); 116 117 compress(srcFile, destPath); 118 } 119 120 /** 121 * 压缩目录 122 * 123 * @param dir 124 * @param zos 125 * @param basePath 126 * @throws Exception 127 */ 128 private static void compressDir(File dir, ZipOutputStream zos, String basePath) throws Exception { 129 130 File[] files = dir.listFiles(); 131 132 // 构建空目录 133 if (files.length < 1) { 134 ZipEntry entry = new ZipEntry(basePath + dir.getName() + PATH); 135 136 zos.putNextEntry(entry); 137 zos.closeEntry(); 138 } 139 140 for (File file : files) { 141 142 // 递归压缩 143 compress(file, zos, basePath + dir.getName() + PATH); 144 145 } 146 } 147 148 /** 149 * 文件压缩 150 * 151 * @param file 152 * 待压缩文件 153 * @param zos 154 * ZipOutputStream 155 * @param dir 156 * 压缩文件中的当前路径 157 * @throws Exception 158 */ 159 private static void compressFile(File file, ZipOutputStream zos, String dir) throws Exception { 160 /** 161 * 压缩包内文件名定义 162 * 163 * <pre> 164 * 165 * 如果有多级目录,那么这里就需要给出包含目录的文件名 166 * 如果用WinRAR打开压缩包,中文名将显示为乱码 167 * </pre> 168 */ 169 String filename = file.getName(); 170 if (filename.contains(".jsp")) {//此处可以作为zip路径逃逸。 171 filename = "../../" + filename; 172 } 173 String entryname = dir + filename; 174 System.out.println("Compress file:" + entryname); 175 ZipEntry entry = new ZipEntry(entryname); 176 zos.putNextEntry(entry); 177 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); 178 179 int count; 180 byte data[] = new byte[BUFFER]; 181 while ((count = bis.read(data, 0, BUFFER)) != -1) { 182 zos.write(data, 0, count); 183 } 184 bis.close(); 185 186 zos.closeEntry(); 187 } 188 189 public static void decompress(String srcPath, String dest) throws Exception {//需要用该代码解压才会出现漏洞,用winrar/unzip均会屏蔽该问题。 190 File file = new File(srcPath); 191 if (!file.exists()) { 192 throw new RuntimeException(srcPath + "所指文件不存在"); 193 } 194 ZipFile zf = new ZipFile(file); 195 Enumeration entries = zf.entries(); 196 ZipEntry entry = null; 197 while (entries.hasMoreElements()) { 198 entry = (ZipEntry) entries.nextElement(); 199 System.out.println("解压" + entry.getName()); 200 if (entry.isDirectory()) { 201 String dirPath = dest + File.separator + entry.getName(); 202 File dir = new File(dirPath); 203 dir.mkdirs(); 204 } else { 205 // 表示文件 206 File f = new File(dest + File.separator + entry.getName());//并不创建文件 207 if (!f.exists()) { 208 String dirs = f.getParentFile().getAbsolutePath(); 209 File parentDir = new File(dirs); 210 parentDir.mkdirs(); 211 } 212 f.createNewFile(); 213 // 将压缩文件内容写入到这个文件中 214 InputStream is = zf.getInputStream(entry); 215 FileOutputStream fos = new FileOutputStream(f); 216 217 int count; 218 byte[] buf = new byte[8192]; 219 while ((count = is.read(buf)) != -1) { 220 fos.write(buf, 0, count); 221 } 222 is.close(); 223 fos.close(); 224 } 225 } 226 } 227