1:新建 ZipUtils 工具类
package com.ly.cloud.datacollection.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ZipUtils {
private static final int BUFFER_SIZE = 10 * 1024;
/**
*
* @param fileList 多文件列表
* @param zipPath 压缩文件临时目录
* @return
*/
public static Boolean zipFiles(List<File> fileList, File zipPath) {
boolean flag = true;
// 1 文件压缩
if (!zipPath.exists()) { // 判断压缩后的文件存在不,不存在则创建
try {
zipPath.createNewFile();
} catch (IOException e) {
flag=false;
e.printStackTrace();
}
}
FileOutputStream fileOutputStream=null;
ZipOutputStream zipOutputStream=null;
FileInputStream fileInputStream=null;
try {
fileOutputStream=new FileOutputStream(zipPath); // 实例化 FileOutputStream对象
zipOutputStream=new ZipOutputStream(fileOutputStream); // 实例化 ZipOutputStream对象
ZipEntry zipEntry=null; // 创建 ZipEntry对象
for (int i=0; i<fileList.size(); i++) { // 遍历源文件数组
fileInputStream = new FileInputStream(fileList.get(i)); // 将源文件数组中的当前文件读入FileInputStream流中
zipEntry = new ZipEntry("("+i+")"+fileList.get(i).getName()); // 实例化ZipEntry对象,源文件数组中的当前文件
zipOutputStream.putNextEntry(zipEntry);
int len; // 该变量记录每次真正读的字节个数
byte[] buffer=new byte[BUFFER_SIZE]; // 定义每次读取的字节数组
while ((len=fileInputStream.read(buffer)) != -1) {
zipOutputStream.write(buffer, 0, len);
}
}
zipOutputStream.closeEntry();
zipOutputStream.close();
fileInputStream.close();
fileOutputStream.close();
} catch (IOException e) {
flag=false;
e.printStackTrace();
} finally {
try {
fileInputStream.close();
zipOutputStream.close();
fileOutputStream.close();
} catch (Exception e){
flag=false;
e.printStackTrace();
}
}
return flag;
}
/**
* @param srcDir 压缩文件夹路径
* @param keepDirStructure 是否保留原来的目录结构,
* true:保留目录结构;
* false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
* @param response
* @throws RuntimeException 压缩失败会抛出运行时异常
*/
public static void toZip(String[] srcDir, String outDir,
boolean keepDirStructure, HttpServletResponse response) throws RuntimeException, Exception {
// 设置输出的格式
response.reset();
response.setContentType("bin");
outDir = URLEncoder.encode(outDir,"UTF-8");
response.addHeader("Content-Disposition","attachment;filename=" + outDir);
OutputStream out = response.getOutputStream();
response.setContentType("application/octet-stream");
ZipOutputStream zos = null;
try {
zos = new ZipOutputStream(out);
List<File> sourceFileList = new ArrayList<File>();
for (String dir : srcDir) {
File sourceFile = new File(dir);
sourceFileList.add(sourceFile);
}
compress(sourceFileList, zos, keepDirStructure);
} catch (Exception e) {
throw new RuntimeException("zip error from ZipUtils", e);
}
finally {
if (zos != null) {
try {
zos.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* @param srcDir 压缩文件夹路径
* @param keepDirStructure 是否保留原来的目录结构,
* true:保留目录结构;
* false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
* @param response
* @throws RuntimeException 压缩失败会抛出运行时异常
*/
public static void toZip(String[] srcDir, String outDir,
boolean keepDirStructure) throws RuntimeException, Exception {
// 设置输出的格式
//outDir = URLEncoder.encode(outDir,"UTF-8");
long start= System.currentTimeMillis();
FileOutputStream out=null;
ZipOutputStream zos = null;
try {
out=new FileOutputStream(outDir); // 实例化 FileOutputStream对象
zos = new ZipOutputStream(out);
List<File> sourceFileList = new ArrayList<File>();
for (String dir : srcDir) {
File sourceFile = new File(dir);
sourceFileList.add(sourceFile);
}
compress(sourceFileList, zos, keepDirStructure);
} catch (Exception e) {
throw new RuntimeException("zip error from ZipUtils", e);
}
finally {
if (zos != null) {
try {
zos.close();
out.close();
log.info(outDir+"压缩完成");
printInfo(start);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 递归压缩方法
*
* @param sourceFile 源文件
* @param zos zip输出流
* @param name 压缩后的名称
* @param keepDirStructure 是否保留原来的目录结构,
* true:保留目录结构;
* false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
* @throws Exception 异常
*/
private static void compress(File sourceFile, ZipOutputStream zos,
String name, boolean keepDirStructure) throws Exception {
byte[] buf = new byte[BUFFER_SIZE];
recursion(sourceFile, zos, name, keepDirStructure, buf);
}
/**
*
* @param sourceFileList 源文件列表
* @param zos zip输出流
* @param keepDirStructure 是否保留原来的目录结构,
* true:保留目录结构;
* false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
* @throws Exception 异常
*/
private static void compress(List<File> sourceFileList,
ZipOutputStream zos, boolean keepDirStructure) throws Exception {
byte[] buf = new byte[BUFFER_SIZE];
for (File sourceFile : sourceFileList) {
String name = sourceFile.getName();
recursion(sourceFile, zos, name, keepDirStructure, buf);
}
}
/**
*
* @param sourceFile 源文件
* @param zos zip输出流
* @param name 文件名
* @param keepDirStructure 否保留原来的目录结构,
* true:保留目录结构;
* false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
* @param buf 字节数组
* @throws Exception 异常
*/
private static void recursion(File sourceFile, ZipOutputStream zos, String name, boolean keepDirStructure, byte[] buf) {
if (sourceFile.isFile()) {
FileInputStream in=null;
try {
in = new FileInputStream(sourceFile);
zos.putNextEntry(new ZipEntry(name));
int len;
while ((len = in.read(buf)) != -1) {
zos.write(buf, 0, len);
}
zos.closeEntry();
in.close();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} else {
File[] listFiles = sourceFile.listFiles();
if (listFiles == null || listFiles.length == 0) {
if (keepDirStructure) {
try {
zos.putNextEntry(new ZipEntry(name + "/"));
zos.closeEntry();
} catch (IOException e) {
e.printStackTrace();
}
}
} else {
for (File file : listFiles) {
if (keepDirStructure) {
try {
compress(file, zos, name + "/" + file.getName(),
true);
} catch (Exception e) {
e.printStackTrace();
}
} else {
try {
compress(file, zos, file.getName(), false);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
public static int deleteFile(File file) {
//判断是否存在此文件
int count=0;
if (file.exists()) {
//判断是否是文件夹
if (file.isDirectory()) {
File[] files = file.listFiles();
//判断文件夹里是否有文件
if (files.length >= 1) {
//遍历文件夹里所有子文件
for (File file1 : files) {
//是文件,直接删除
if (file1.isFile()) {
count++;
file1.delete();
} else {
//是文件夹,递归
count++;
deleteFile(file1);
}
}
//file此时已经是空文件夹
file.delete();
} else {
//是空文件夹,直接删除
file.delete();
}
} else {
//是文件,直接删除
file.delete();
}
} else {
}
return count;
}
public static void downloadFile(String path, File file, String outDir, HttpServletResponse response){
OutputStream os = null;
FileInputStream fis=null;
try {
fis = new FileInputStream(file);
// 取得输出流
os = response.getOutputStream();
//String contentType = Files.probeContentType(Paths.get(file.getAbsolutePath()));
outDir = URLEncoder.encode(outDir,"UTF-8");
response.addHeader("Content-Disposition","attachment;filename=" + outDir);
response.setContentType("application/octet-stream");
response.setHeader("Content-Length", String.valueOf(file.length()));
//response.setHeader("Content-Disposition", "attachment;filename="+ outDir);
//response.setHeader("Content-Disposition", "attachment;filename="+ new String(file.getName().getBytes("utf-8"),"ISO8859-1"));
/*
* int len; // 该变量记录每次真正读的字节个数 byte[] buffer=new byte[BUFFER_SIZE]; //
* 定义每次读取的字节数组 while ((len=fis.read(buffer)) != -1) { os.write(buffer, 0, len);
* }
*/
WritableByteChannel writableByteChannel = Channels.newChannel(os);
FileChannel fileChannel = fis.getChannel();
ByteBuffer buffer=ByteBuffer.allocate(BUFFER_SIZE);
long total=0L;
int len=0;
while((len=fileChannel.read(buffer))!=-1){
total=total+len;
buffer.flip();
// 保证缓冲区的数据全部写入
while (buffer.hasRemaining())
{
writableByteChannel.write(buffer);
}
buffer.clear();
}
log.info(outDir+"下载完成");
os.flush();
fileChannel.close();
writableByteChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
//文件的关闭放在finally中
finally {
try {
if (fis != null) {
fis.close();
}
if (os != null) {
os.flush();
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void printInfo(long beginTime) {
long endTime = System.currentTimeMillis();
long total = endTime - beginTime;
log.info("压缩耗时:" + total / 1000 + "秒");
}
}
2:简单测试
@GetMapping(value = "/zip")
@AnonymityAnnotation(access = true)
public WebResponse<String> zip(@RequestParam("file") MultipartFile file) throws IOException {
InputStream stream = file.getInputStream();
System.out.println(stream);
//下载压缩后的地址
String path = "D:/91-69ddf076d28040d29e59aec22b65b150";
//获取文件原本的名称
String fileName = file.getOriginalFilename();
System.out.println(fileName);
String[] src = { path + "/" + fileName };
String outDir = path + "/69.zip";
try {
ZipUtils.toZip(src, outDir, true);
} catch (Exception e) {
}
return new WebResponse<String>().success("OK");
}
3:效果图