前言
在实际项目中,我们可能会接到将文件或者资料打包压缩导出的需求,例如将系统中某些生成的文件一起打包压缩下载提供给客户使用,今天提供一个jdk自带的工具类快速实现打包压缩的功能,方法我已经封装好,大家如果在项目中遇到类似需求可以直接复制过去使用
一、思路和步骤
首先将我们在系统上生成的文件或者服务器上现有的文件读取到输出流中,然后传给zip压缩流实现压缩并响应到浏览器下载
具体步骤:
1、将文件转换为流
2、将生成好的文件流数据和文件名(压缩包内一个文件对应一个文件名)封装
3、将数据添加到压缩流中进行压缩
4、响应到浏览器下载
5、关闭流
二、工具类封装
下面是一个工具类封装和具体实现
1、封装一个数据实体
import lombok.AllArgsConstructor;
import lombok.Data;/*** @Author: 你住过的屋檐* @Date: 2025/2/26 下午5:34* @aphorism You are lucky to have someone to help you.No one to help you, is just fate.No one should do anything for you, because life is your own, you are responsible for yourself*/
@Data
@AllArgsConstructor
public class FileData {/*** 文件名*/private String fileName;/*** 文件流字节数组*/private byte[] fileByte;
}
2、工具类
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;/*** @Author: 你住过的屋檐* @Date: 2025/2/26 下午4:01* @aphorism You are lucky to have someone to help you.No one to help you, is just fate.No one should do anything for you, because life is your own, you are responsible for yourself*/
public class ZipUtils {/*** 压缩文件并下载* @param zipName 压缩包名称* @param fileDataList 压缩数据流* @param response 响应对象* @throws IOException*/public static void downLoadZip(String zipName, List<FileData> fileDataList, HttpServletResponse response) throws IOException {if(fileDataList==null||fileDataList.isEmpty()){throw new IOException("数据为空");}ByteArrayOutputStream zipOutputStream = new ByteArrayOutputStream();ZipOutputStream zos = new ZipOutputStream(zipOutputStream);for (FileData fileData : fileDataList) {// 添加文件到 ZIP件中addFileToZip(zos, fileData.getFileName(), fileData.getFileByte());}// finish()方法用于完成当前 ZIP 文件的写入。它会写入 ZIP 文件的结束记录,确保 ZIP 文件的完整性zos.finish();//关闭 ZipOutputStream,释放资源zos.close();// 创建输入流资源ByteArrayInputStream in = new ByteArrayInputStream(zipOutputStream.toByteArray());// 设置响应头,通知浏览器下载response.setContentType("application/force-download");String fileName= URLEncoder.encode(zipName,"utf-8");response.setHeader("Content-disposition", "attachment; filename="+fileName );response.setContentLength(in.available());OutputStream out = response.getOutputStream();byte[] b= new byte[1024];int len;while((len=in.read(b))!=-1){out.write(b,0,len);}//用于强制将缓冲区中的数据立即写入到目标输出流中,避免数据丢失。out.flush();//关闭输出流并释放资源out.close();//关闭输入流并释放资源in.close();}/*** 添加文件到 ZIP 文件中* @param zipOut* @param fileName 文件名* @param content 添加内容* @throws IOException*/private static void addFileToZip(ZipOutputStream zipOut, String fileName, byte[] content) throws IOException {ZipEntry zipEntry = new ZipEntry(fileName);zipOut.putNextEntry(zipEntry);zipOut.write(content);zipOut.closeEntry();}
}
三、实现效果
下面是演示效果
1、在D盘创建了一个文档,写一个hello world!
2、写一个调用接口
import com.customs.broker.utils.zip.FileData;
import com.customs.broker.utils.zip.ZipUtils;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;@RestController
public class TestController {@GetMapping("/download")public void downLoadZip(HttpServletResponse response){try {File file = new File("D:\\测试文档.txt");//转换为输入流FileInputStream fis = new FileInputStream(file);ByteArrayOutputStream outputStream = new ByteArrayOutputStream();//读取文件到输出流中byte[] buffer = new byte[1024];int len;while ((len = fis.read(buffer)) != -1) {outputStream.write(buffer, 0, len);}List<FileData> fileDataList = new ArrayList<>();//将文件流和文件名封装进实体FileData fileData = new FileData("测试文档.txt", outputStream.toByteArray());//添加fileDataList.add(fileData);//执行压缩打包下载ZipUtils.downLoadZip("test.zip",fileDataList,response);} catch (IOException e) {e.printStackTrace();}}}
3、启动项目后浏览器执行调用接口
http://127.0.0.1:8080/download
直接生成了压缩包并且下载到了浏览器
打包压缩包已经将hello world!的文档压缩进压缩包
为了帮助更多像你一样的读者,我将持续在专栏中分享技术干货和实用技巧。如果你觉得这篇文章对你有帮助,可以考虑关注我的专栏,谢谢。