Java实现多级目录文件下载压缩包

一、首先需要查出来目录和文件的集合,我这边是直接查好的文件和目录,也可以单独查询目录和文件,然后在进行拼装。注意不能将zipOutPutStream.finish()和zipOutPutStream.close()同时使用,会导致压缩包是不可预料的压缩文件末端,这个问题解决了好久,才发现是这个导致的。

如果空文件夹也需要压缩,采用的是以下的方法:

 zipOutputStream.putNextEntry(new ZipEntry(emptyFolderList.get(i) + " /"));
/*根据业务id查询的文件和目录集合*/
            List<SchemeFileCatalog> list = schemeFileCatalogService.getDetails(busKey);

            if (list != null && list.size() > 0) {
                String zipName =  "方案附件信息.zip";
                response.setContentType("application/octet-stream");// 指明response的返回对象是文件流
                response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(zipName, "UTF-8"));
               // ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(new File("D:/a/a.zip")));
                ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
                zipOutputStream.setMethod(ZipOutputStream.DEFLATED);//设置压缩方法

                try {
//声明一个存放文件路径的集合
                    List<File> files = new ArrayList<File>();
                    //文件夹名
                    List<String> totalFolderList = new ArrayList<String>();
                    for (int i = 0;i < list.size(); i++){
                        //当前目录名
                        String superFolderName = list.get(i).getFileName();
                        // 查询该目录下的文件
                        List<SysFileInfoVo> children = list.get(i).getChildren();
                        for (int j = 0; j < children.size(); j++) {
                            //文件名
                            String fileName = children.get(j).getFileName();
                            //获取文件在本地的地址
                            String filePath = FileUtils.appendFilePath(basedir, children.get(j).getPath().substring(8));
                            //构建二级文件夹名
                            totalFolderList.add(superFolderName + "\\" + fileName + "\\");
                            files.add(new File(filePath));
                        }

                    }
                    if (CollectionUtils.isEmpty(files) == false) {
                        for (int i = 0, size = totalFolderList.size(); i < size; i++) {
                            //调用工具类方法
                            ZipUtils.compress(files.get(i), zipOutputStream, totalFolderList.get(i));
                        }
                        //强行把Buffer的 内容写到客户端浏览器
                        response.flushBuffer();
                        // 冲刷输出流
                        zipOutputStream.flush();
            //            zipOutputStream.finish();
                        // 关闭输出流
                        zipOutputStream.close();
                    }
                    else {
                        outWriter = response.getWriter();
                        outWriter.println("<script>alert('该日期暂无文件')';</script>");
                        return;
                    }
                } catch (Exception e) {
                    try {
                        outWriter = response.getWriter();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                    logger.error("ImportfileController.java-packdownload-Exception: ", e);
                    outWriter.println("<script>alert('下载异常')';</script>");
                    return;
                }
            }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

二、下边的这个是工具类,如果对上边的代码有疑问可以在工具类中的main方法进行单独的尝试,按照实例来传参就可以了。

package com.mesing.mldp.system.utils;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;

import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;

public class ZipUtils {

        private static Logger logger = LoggerFactory.getLogger(ZipUtils.class);
        // 目录标识判断符
        private static final String PATCH = "/";
        // 基目录
        private static final String BASE_DIR = "/b/";
        // 缓冲区大小
        private static final int BUFFER = 2048;
        // 字符集
        private static final String CHAR_SET = "UTF-8";

        public static void compress(File srcFile, ZipOutputStream zipOutputStream, String basePath) throws Exception {
            if (srcFile.isDirectory()) {
                compressDir(srcFile, zipOutputStream, basePath);
            } else {
                compressFile(srcFile, zipOutputStream, basePath);
            }
        }


        private static void compressDir(File dir, ZipOutputStream zipOutputStream, String basePath) throws Exception {
            try {
                // 获取文件列表
                File[] files = dir.listFiles();

                if (files.length < 1) {
                    ZipEntry zipEntry = new ZipEntry(basePath + dir.getName() + PATCH);

                    zipOutputStream.putNextEntry(zipEntry);
                    zipOutputStream.closeEntry();
                }

                for (int i = 0,size = files.length; i < size; i++) {
                    compress(files[i], zipOutputStream, basePath + dir.getName() + PATCH);
                }
            } catch (Exception e) {
                throw new Exception(e.getMessage(), e);
            }
        }

        private static void compressFile(File file, ZipOutputStream zipOutputStream, String dir) throws Exception {
            try {
                // 压缩文件
                ZipEntry zipEntry = new ZipEntry(dir + file.getName());
                zipOutputStream.putNextEntry(zipEntry);

                // 读取文件
                BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));

                int count = 0;
                byte data[] = new byte[BUFFER];
                while ((count = bis.read(data, 0, BUFFER)) != -1) {
                    zipOutputStream.write(data, 0, count);
                }
                bis.close();
                zipOutputStream.closeEntry();
            } catch (Exception e) {
                throw new Exception(e.getMessage(),e);
            }
        }


        public static void main(String[] args) {
            try {
                ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(new File("D:/a/a.zip")));
                zipOutputStream.setEncoding(CHAR_SET);

                List<File> files = new ArrayList<File>();
                files.add(new File("F:\\fileStorage\\template\\upload\\2023\\01\\16\\8d8ec9b8-de59-4476-8bd2-c1b667ca71b0.docx"));
                files.add(new File("F:\\fileStorage\\template\\upload\\2023\\01\\16\\38e99679-346d-4832-a8e0-151f7d7886e0.docx"));

                if (CollectionUtils.isEmpty(files) == false) {
                    for (int i = 0,size = files.size(); i < size; i++) {
                        compress(files.get(i), zipOutputStream, BASE_DIR);
                    }
                }
                // 冲刷输出流
                zipOutputStream.flush();
                // 关闭输出流
                zipOutputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

三、我使用的 前端是vue,在此方法传参的地方一定要设置上

export function packdownload(query) {
  return request({
    url: '/scheme/catalog/packdownload',
    method: 'get',
    params: query,
    responseType: 'blob',
  })
}
responseType: 'blob',

这个很重要,不然会导致压缩文件损坏。

packdownload({
  busKey: ""
}).then(response => {
  console.log(response);
    let blob = new Blob([response], {type: "application/zip"});
    let url = window.URL.createObjectURL(blob);
    const link = document.createElement("a"); // 创建a标签
    link.href = url;
    link.download = "方案附件信息.zip"; // 重命名文件
    link.click();
    URL.revokeObjectURL(url); // 释放内存
  }).catch(function (err) {
    console.log(err);
  });

四、最后的效果就是

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值