Vue + SpringBoot + zip4j实现文件的压缩下载

Vue + SpringBoot + zip4j实现文件的压缩下载序言最近在项目当中遇到一个需要解压文件为 zip 通过前端进行下载 这和常规的文件下载不同 在 zip 文件还会存在目录 目录中再存放文件 当时找了很多资料都不尽人意 所以自己写了这篇文字供以后参考 SpringBoot 的版本为 2 5 15

大家好,欢迎来到IT知识分享网。

序言

最近在项目当中遇到一个需要解压文件为zip,通过前端进行下载,这和常规的文件下载不同,在 zip 文件还会存在目录,目录中再存放文件,当时找了很多资料都不尽人意,所以自己写了这篇文字供以后参考。SpringBoot 的版本为2.5.15,zip4j 的版本为 2.11.5

Zip4j

zip4j是一个功能强大的 Java 库,专门用于处理 ZIP 文件格式。它提供了一系列易于使用的 API,使得开发人员可以方便地在 Java 应用程序中执行各种 ZIP 文件操作,包括创建、读取、更新和提取 ZIP 文件等。GitHub地址 里面说明了各种 API 的使用和示例。

思路

具体思路是打算通过 zip4j 创建一个 zip 文件,然后通过 API 在 zip 文件里面创建目录和文件。当时的业务需求是下载每一个文件的附录文件,每一个文件都会有多个附录文件,不可能去一个个下载,所以需压缩为 zip 格式。具体的代码如下:

/ * 创建 zip 文件 * * @param ids 文件id集合 * @return zip 文件的路径 */ private String createZipFile(String ids) { Integer[] intArray = Convert.toIntArray(ids); // 创建一个列表用于存放所有附件文件的路径,后续统一压缩到一个zip文件中 List<String> allFilePaths = new ArrayList<>(); // 循环查询每个id对应的附件文件路径并添加到列表中 // 里面的代码大家可能会觉得麻烦,不用细看,只需要知道这层for循环是为了找到附录文件在磁盘的地址 for (int id : intArray) { List<SysDownloadCenterAttachment> attachmentList = sysDownloadCenterAttachmentMapper.selectList(new LambdaQueryWrapper<SysDownloadCenterAttachment>() .eq(SysDownloadCenterAttachment::getDownloadCenterId, id)); if (!CollectionUtils.isEmpty(attachmentList)) { List<String> filePaths = attachmentList.stream().map(attachment -> { String filePath = scjtConfig.getUploadPath() + attachment.getLocation(); if (!StringUtils.startsWith(filePath, "D:")) { filePath = "D:" + filePath; } return filePath; }).collect(Collectors.toList()); allFilePaths.addAll(filePaths); } } // 创建ZipFile对象,指定zip文件的路径 ZipFile zipFile = new ZipFile("d:/filename.zip"); // 循环附录文件地址 for (String filePath : allFilePaths) { File file = new File(filePath); if (file.exists()) { // 获取文件名(包含后缀) String fileName = file.getName(); // 这里假设附件所属的id可以通过某种方式获取,比如从文件路径解析或者其他逻辑判断,示例中用一个方法 getFileIdFromPath 来表示获取id的逻辑,你需要根据实际情况替换 String folderNameInsideZip = getFileTitleFromPath(intArray, filePath); // 构造在zip文件中存放的路径,格式为 "id标识的文件夹名/原文件名" try { // 尝试获取目标文件夹在zip文件中的FileHeader FileHeader folderHeader = zipFile.getFileHeader(folderNameInsideZip + "/"); log.info("文件夹在zip文件中的FileHeader:" + folderHeader); // 如果zip文件中指定目录不存在,则创建,这一步判断是必须的,不然会导致下一次文件添加动作会覆盖之前的文件 if (Objects.isNull(folderHeader)) { new File(folderNameInsideZip).mkdirs(); // 创建文件夹 ZipParameters folderPar = new ZipParameters(); folderPar.setCompressionLevel(CompressionLevel.NORMAL); folderPar.setEncryptFiles(false); zipFile.addFolder(new File(folderNameInsideZip), folderPar); log.info("文件夹已成功添加到zip文件中。"); } // 创建ZipParameters对象,用于设置添加文件的参数 ZipParameters parameters = new ZipParameters(); // 设置压缩方法,这里使用默认压缩方法 parameters.setCompressionMethod(CompressionMethod.DEFLATE); // 设置压缩级别,这里使用默认压缩级别 parameters.setCompressionLevel(CompressionLevel.NORMAL); // 设置添加文件在zip文件中的路径,格式为 "文件夹名/文件名" parameters.setFileNameInZip(folderNameInsideZip + "/" + file.getName()); // 将文件添加到zip文件中的指定文件夹路径下 zipFile.addFile(file, parameters); log.info("文件已成功添加到zip文件中的指定文件夹。"); } catch (ZipException e) { throw new RuntimeException(e); } } } return zipFile.getFile().getAbsolutePath(); }

上面代码运行完毕,就会在d:/filename.zip的位置存在一个 zip 文件,打开后会看到目录结构和文件信息。接下来就需要前端来下载这个 zip 文件,我这里建立下载后就删除这个 zip 文件,这样下次重新生成时就不会出现文件合并的问题。后端下载代码如下:

/ * 下载文件的附件,附件较多 压缩为zip下载 * * @param ids 文件id集合 * @param response * @return */ @Override @SneakyThrows public ResponseEntity<Resource> downloadZip(String ids, HttpServletResponse response) { // 创建zip文件 String zipFilePath = createZipFile(ids); File file = new File(zipFilePath); InputStreamResource resource = new InputStreamResource(new FileInputStream(file)); return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=sample.zip") .contentType(MediaType.APPLICATION_OCTET_STREAM) .contentLength(file.length()) .body(resource); }

前段代码如下:

export function downloadCenterZip(ids) { return request({ url: `/system/download/center/downloadZip`, method: 'post', data: ids, responseType: 'blob' // 标识返回类型为blob }) }
/ * 下载按钮操作 */ function handleDownloadZip() { downloadCenterZip(ids.value.toString()).then(res => { console.log(res) const url = window.URL.createObjectURL(new Blob([res], {type: 'application/zip'})); let a = document.createElement('a') a.href = url a.download = 'download.zip' a.click() URL.revokeObjectURL(url) // 释放内存 a.remove() }) }

总结

对于其他格式文件的下载,其实思路都差不多,后端都需要返回一个blob或者byte数组,然后前端使用超链接的方式来触发下载。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/188504.html

(0)
上一篇 2025-09-20 08:10
下一篇 2025-09-20 08:26

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信