前端:
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()前面加父文件夾,此時壓縮包中的文件就會都在根目錄下,但是此方法需要手動去處理文件名稱重復的問題