zip压缩文件并下载(不保存压缩包直接下载)
前端:
function downloadzip() { window.location.href = "${basePath}/system/sysMerch/downloadzip"; }
后端(controller):
@RequestMapping(value = "downloadzip") public void downloadzip(String id, HttpServletRequest request, HttpServletResponse response) {
// 要压缩的文件/文件夹目录 String rootZipUrl = Global.getProperty("VOUCHER_IMAGE_DIR"); File rootFile = new File(rootZipUrl); if (!rootFile.exists()) { LOG.error("当前文件夹不存在", rootZipUrl); return; } FileUtils.downloadZip(response, rootZipUrl,"压缩包"); }
压缩工具类:
/** * 下载并压缩文件 * * @param response * @param srcDir 原文件/目录路径 * @param zipFileName 压缩包名称 * @return void*/ public static void downloadZip(HttpServletResponse response, String srcDir, String zipFileName) { long start = System.currentTimeMillis(); ZipOutputStream zos = null; try { response.reset(); response.setCharacterEncoding("UTF-8"); response.setContentType("application/octet-stream;charset=UTF-8"); // inline在浏览器中直接显示,不提示用户下载 // attachment弹出对话框,提示用户进行下载保存本地 // 默认为inline方式 zipFileName = zipFileName + ".zip"; // 处理中文文件名的问题 zipFileName = URLEncoder.encode(zipFileName, "UTF-8"); zipFileName = new String(zipFileName.getBytes("UTF-8"), "GBK"); response.setHeader("Content-Disposition", "attachment;filename=" + zipFileName); zos = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream())); File sourceFile = new File(srcDir); zipFile(sourceFile, zos, ""); long end = System.currentTimeMillis(); System.out.println("压缩完成,耗时:" + (end - start) + " ms"); } catch (IOException e) { e.printStackTrace(); logger.error("下载zip文件出错", e); } finally { if (null != zos) { try { zos.close(); } catch (IOException e) { e.printStackTrace(); logger.error("关闭压缩流出错", e); } } } }
递归将文件放入压缩包(此压缩包保持原文件夹目录结构):
/** * 递归添加文件到压缩包 * * @param sourceFile 原文件 * @param zos 压缩流 * @param zipFileName 压缩目录 * @return void * @author chen.bing * @Date 2019/11/4 15:50 */ private static void zipFile(File sourceFile, ZipOutputStream zos, String zipFileName) { //设置读取数据缓存大小 byte[] buffer = new byte[4096]; try { if (sourceFile.exists()) { if (sourceFile.isFile() && !sourceFile.isDirectory()) { zos.putNextEntry(new ZipEntry(zipFileName)); int len; FileInputStream in = new FileInputStream(sourceFile); while ((len = in.read(buffer)) != -1) { zos.write(buffer, 0, len); } zos.closeEntry(); in.close(); } else { File[] listFiles = sourceFile.listFiles(); if (listFiles == null || listFiles.length == 0) { // 需要保留原来的文件结构时,需要对空文件夹进行处理 // 空文件夹的处理 zos.putNextEntry(new ZipEntry(zipFileName + "/")); // 没有文件,不需要文件的copy zos.closeEntry(); } else { zipFileName = zipFileName.length() == 0 ? "" : zipFileName + "/"; for (File file : listFiles) { // 注意:file.getName()前面需要带上父文件夹的名字加一斜杠, // 不然最后压缩包中就不能保留原来的文件结构,即:所有文件都跑到压缩包根目录下了 zipFile(file, zos, zipFileName + file.getName()); } } } } } catch (IOException e) { e.printStackTrace(); logger.error("压缩文件出错", e); } }
注:如果不想保留原文件的目录结构则去掉空文件夹的处理以及在file.getName()前面加父文件夹,此时压缩包中的文件就会都在根目录下,但是此方法需要手动去处理文件名称重复的问题