首页 > 技术文章 > zip压缩文件并下载(不保存压缩包直接下载)

fatTmonkey 2019-11-06 14:33 原文

前端:

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()前面加父文件夹,此时压缩包中的文件就会都在根目录下,但是此方法需要手动去处理文件名称重复的问题

 

推荐阅读