当前位置: 首页 > news >正文

java实现压缩文件夹(层级压缩)下载,java打包压缩文件夹下载

工具类如下
打包下载方法:exportZip(支持整个文件夹或单文件一起)
注意:前端发送请求不能用ajax,form表单提交可以,location.href也可以,window.open也可以,总之就ajax请求就是不行

import com.leatop.common.utils.StringUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.channels.FileChannel;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;public class FileToZipUtils {// 日志private static Logger log = LoggerFactory.getLogger(FileToZipUtils.class);// 创建文件夹public static String CreateFile(String dir) {File file = new File(dir);if (!file.exists()) {//创建文件夹boolean mkdir = file.mkdir();} else {}return dir;}// 复制文件public static void copyFile(File source, File dest) throws IOException {FileChannel inputChannel = null;FileChannel outputChannel = null;try {inputChannel = new FileInputStream(source).getChannel();outputChannel = new FileOutputStream(dest).getChannel();outputChannel.transferFrom(inputChannel, 0, inputChannel.size());} finally {inputChannel.close();outputChannel.close();}}// 删除文件public void delFile(File file) {File[] listFiles = file.listFiles();if (listFiles != null) {for (File f : listFiles) {if (f.isDirectory()) {delFile(f);} else {f.delete();}}}file.delete();}/*** 通过递归逐层删除文件信息** @param filePath*/public static void deleteFileByIO(String filePath) {File file = new File(filePath);File[] list = file.listFiles();if (list != null) {for (File temp : list) {deleteFileByIO(temp.getAbsolutePath());}}file.delete();}/*** 将指定路径下的所有文件打包zip导出** @param response       HttpServletResponse* @param sourceFilePath 要打包的路径* @param fileName       下载时的文件名称*                       //     * @param postfix 下载时的文件后缀 .zip/.rar*/public static void exportZip(HttpServletResponse response, String sourceFilePath, String fileName) {// 默认文件名以时间戳作为前缀SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");String downloadName = sdf.format(new Date()) + fileName;// 将文件进行打包下载try {OutputStream os = response.getOutputStream();// 接收压缩包字节byte[] data = createZip(sourceFilePath);response.reset();response.setCharacterEncoding("UTF-8");response.addHeader("Access-Control-Allow-Origin", "*");response.setHeader("Access-Control-Expose-Headers", "*");// 下载文件名乱码问题response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));//response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName);response.addHeader("Content-Length", "" + data.length);response.setContentType("application/octet-stream;charset=UTF-8");IOUtils.write(data, os);os.flush();os.close();} catch (Exception e) {e.printStackTrace();}}/**** 压缩文件变成zip输出流*/public static byte[] createZip(String srcSource) throws Exception {ByteArrayOutputStream outputStream = new ByteArrayOutputStream();ZipOutputStream zip = new ZipOutputStream(outputStream);//将目标文件打包成zip导出File file = new File(srcSource);createAllFile(zip, file, "");IOUtils.closeQuietly(zip);return outputStream.toByteArray();}/**** 对文件下的文件处理*/public static void createAllFile(ZipOutputStream zip, File file, String dir) throws Exception {//如果当前的是文件夹,则进行进一步处理if (file.isDirectory()) {//得到文件列表信息File[] files = file.listFiles();//将文件夹添加到下一级打包目录zip.putNextEntry(new ZipEntry(dir + "/"));dir = dir.length() == 0 ? "" : dir + "/";//循环将文件夹中的文件打包for (int i = 0; i < files.length; i++) {createAllFile(zip, files[i], dir + files[i].getName());                 //递归处理}} else {     //当前的是文件,打包处理//文件输入流BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));ZipEntry entry = new ZipEntry(dir);zip.putNextEntry(entry);zip.write(FileUtils.readFileToByteArray(file));IOUtils.closeQuietly(bis);zip.flush();zip.closeEntry();}}/*** 将存放在sourceFilePath目录下的源文件,打包成fileName名称的zip文件,并存放到zipFilePath路径下** @param sourceFilePath :待压缩的文件路径* @param zipFilePath    :压缩后存放路径* @param fileName       :压缩后文件的名称* @return*/public static boolean fileToZip(String sourceFilePath, String zipFilePath, String fileName) {boolean flag = false;File sourceFile = new File(sourceFilePath);FileInputStream fis = null;BufferedInputStream bis = null;FileOutputStream fos = null;ZipOutputStream zos = null;if (sourceFile.exists() == false) {log.info("待压缩的文件目录:" + sourceFilePath + "不存在.");} else {try {File zipFile = new File(zipFilePath + "/" + fileName + ".zip");if (zipFile.exists()) {log.info(zipFilePath + "目录下存在名字为:" + fileName + ".zip" + "打包文件.");} else {File[] sourceFiles = sourceFile.listFiles();if (null == sourceFiles || sourceFiles.length < 1) {log.info("待压缩的文件目录:" + sourceFilePath + "里面不存在文件,无需压缩.");} else {fos = new FileOutputStream(zipFile);zos = new ZipOutputStream(new BufferedOutputStream(fos));byte[] bufs = new byte[1024 * 10];for (int i = 0; i < sourceFiles.length; i++) {// 创建ZIP实体,并添加进压缩包ZipEntry zipEntry = new ZipEntry(sourceFiles[i].getName());zos.putNextEntry(zipEntry);// 读取待压缩的文件并写进压缩包里fis = new FileInputStream(sourceFiles[i]);bis = new BufferedInputStream(fis, 1024 * 10);int read = 0;while ((read = bis.read(bufs, 0, 1024 * 10)) != -1) {zos.write(bufs, 0, read);}}flag = true;}}} catch (FileNotFoundException e) {e.printStackTrace();throw new RuntimeException(e);} catch (IOException e) {e.printStackTrace();throw new RuntimeException(e);} finally {// 关闭流try {if (null != bis)bis.close();if (null != zos)zos.close();} catch (IOException e) {e.printStackTrace();throw new RuntimeException(e);}}}return flag;}/*** 解压缩zip包** @param zipFilePath        需要解压的zip文件的全路径* @param unzipFilePath      解压后的文件保存的路径* @param includeZipFileName 解压后的文件保存的路径是否包含压缩文件的文件名。true-包含;false-不包含*/@SuppressWarnings("unchecked")public static void unzip(String zipFilePath, String unzipFilePath, boolean includeZipFileName) throws Exception {if (StringUtils.isNotBlank(zipFilePath) || StringUtils.isNotBlank(unzipFilePath)) {File zipFile = new File(zipFilePath);// 如果解压后的文件保存路径包含压缩文件的文件名,则追加该文件名到解压路径if (includeZipFileName) {String fileName = zipFile.getName();if (StringUtils.isNotEmpty(fileName)) {fileName = fileName.substring(0, fileName.lastIndexOf("."));}unzipFilePath = unzipFilePath + File.separator + fileName;}// 创建解压缩文件保存的路径File unzipFileDir = new File(unzipFilePath);if (!unzipFileDir.exists() || !unzipFileDir.isDirectory()) {unzipFileDir.mkdirs();}                        // 开始解压ZipEntry entry = null;String entryFilePath = null, entryDirPath = null;File entryFile = null, entryDir = null;int index = 0, count = 0, bufferSize = 1024;byte[] buffer = new byte[bufferSize];BufferedInputStream bis = null;BufferedOutputStream bos = null;ZipFile zip = new ZipFile(zipFile);Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) zip.entries();// 循环对压缩包里的每一个文件进行解压while (entries.hasMoreElements()) {entry = entries.nextElement();// 构建压缩包中一个文件解压后保存的文件全路径entryFilePath = unzipFilePath + File.separator + entry.getName();// 构建解压后保存的文件夹路径index = entryFilePath.lastIndexOf(File.separator);if (index != -1) {entryDirPath = entryFilePath.substring(0, index);} else {entryDirPath = "";}entryDir = new File(entryDirPath);// 如果文件夹路径不存在,则创建文件夹if (!entryDir.exists() || !entryDir.isDirectory()) {entryDir.mkdirs();}                                // 创建解压文件entryFile = new File(entryFilePath);if (entryFile.exists()) {// 检测文件是否允许删除,如果不允许删除,将会抛出SecurityExceptionSecurityManager securityManager = new SecurityManager();securityManager.checkDelete(entryFilePath);// 删除已存在的目标文件entryFile.delete();}                                // 写入文件bos = new BufferedOutputStream(new FileOutputStream(entryFile));bis = new BufferedInputStream(zip.getInputStream(entry));while ((count = bis.read(buffer, 0, bufferSize)) != -1) {bos.write(buffer, 0, count);}bos.flush();bos.close();}zip.close();// 切记一定要关闭掉,不然在同一个线程,你想解压到临时路径之后,再去删除掉这些临时数据,那么就删除不了}}}
http://www.lryc.cn/news/318193.html

相关文章:

  • Visual Studio 2022 配置“Debug|x64”的 Designtime 生成失败。IntelliSense 可能不可用。
  • Pandas教程16:DataFrame列标题批量重命名+空df数据判断+列名顺序重排
  • React.FC介绍
  • 为什么要用scrapy爬虫库?而不是纯python进行爬虫?
  • C:数据结构王道
  • Compose UI 之 Buttons 按钮 IconButtons 图标按钮
  • 吴恩达机器学习笔记 二十一 迁移学习 预训练
  • Python中Pandas常用函数及案例详解
  • VR全景看房:超越传统的看房方式
  • pip 配置镜像加速安装
  • LUA语法复习总结
  • 某赛通电子文档安全管理系统 DecryptApplication 任意文件读取漏洞(2024年3月发布)
  • Mac-自动操作 实现双击即可执行shell脚本
  • 人工智能入门之旅:从基础知识到实战应用(六)
  • Debezium日常分享系列之:Debezium2.5稳定版本之Mysql连接器的工作原理
  • Linux服务器,使用ssh登录时越来越慢,有时甚至出现超时的现象,解决方案
  • GPT-SoVITS开源音色克隆框架的训练与调试
  • C#十大排序总结
  • Vue首屏优化方案
  • SpringBoot使用log4j2将日志记录到文件及自定义数据库
  • vue+elementUI用户修改密码的前端验证
  • 微信小程序问题定位——sourcemap文件
  • Photoshop_00000
  • rviz上不显示机器人模型(模型只有白色)
  • Android 录屏操作
  • 基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的血细胞智能检测与计数(深度学习模型+UI界面代码+训练数据集)
  • Selenium 学习(0.20)——软件测试之单元测试
  • 章六、集合(1)—— 概念、API、List 接口及实现类、集合迭代
  • 原生js html5 canvas制作flappy bird压扁小鸟游戏
  • 服务器集群 -- nginx配置tcp负载均衡