文件夹、文件目录递归下载:打包成ZIP压缩包

文件目录下载并打包成ZIP压缩包

在Java中如果要实现文件夹、文件目录的递归下载并打包成ZIP压缩包,可以通过以下步骤进行:

 

python

代码解读

复制代码

遍历文件夹:使用递归方法遍历指定目录下的所有文件和文件夹 创建ZIP输出流:使用java.util.zip包中的ZipOutputStream类创建ZIP文件 将文件添加到ZIP:将遍历到的文件逐个添加到ZIP压缩包中

单个文件目录打包ZIP下载

单个文件目录打包ZIP下载与文件目录递归打包ZIP下载类似,首先来看看单个文件目录中的文件是如何打包ZIP下载的。

 

java

代码解读

复制代码

/** * 下载指定文件夹及其所有文件的内容,并将其打包为 ZIP 文件。 * * @param folderId 需要下载的文件夹 ID * @param response HTTP 响应对象,用于发送 ZIP 文件 * @throws IOException 在处理输入输出时可能抛出异常 */ public void downloadFolder(Integer folderId, HttpServletResponse response) throws IOException { // 校验权限,检查用户是否有权限下载该文件夹 Boolean isAuth = checkAuthService.checkAuthDownload(folderId); if (!isAuth) { // 如果没有权限,则抛出业务异常 throw new BusinessException(TipsConstant.Tips_6002); } // 查询指定文件夹下的所有文件列表 List<FileOrg> fileOrgList = getFileBeansByFolderId(folderId); // 获取文件夹信息,用于设置 ZIP 文件的名称 FolderOrg folderOrg = folderOrgMappr.selectById(folderId); // 准备压缩文件的数据 try (ZipOutputStream zipOutputStream = new ZipOutputStream(response.getOutputStream())) { // 设置响应头,准备发送 ZIP 文件 prepareResponse(response, folderOrg.getName()); // 将文件添加到 ZIP 压缩包中 addFilesToZip(zipOutputStream, fileOrgList, folderOrg.getName()); } catch (IOException e) { // 如果发生错误,返回 500 错误和错误信息 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to download folder: " + e.getMessage()); } }

这里首先假设有一个目录:测试目录,里面有文件与文件目录。以下是针对单个文件目录打包ZIP下载实现的一个效果截图。 

递归文件目录打包ZIP下载

递归文件目录打包ZIP下载相比单个文件目录打包ZIP下载,无非是多了个递归文件目录的操作。

 

java

代码解读

复制代码

@Override public void recursiveDownload(Integer folderId, HttpServletResponse response) throws IOException { // 校验权限,检查用户是否有权限下载该文件夹 Boolean isAuth = checkAuthService.checkAuthDownload(folderId); if (!isAuth) { // 如果没有权限,则抛出业务异常 throw new BusinessException(TipsConstant.Tips_6002); } // 获取文件夹信息,用于设置 ZIP 文件的名称 FolderOrg folderOrg = folderOrgMappr.selectById(folderId); // 准备压缩文件的数据 try (ZipOutputStream zipOutputStream = new ZipOutputStream(response.getOutputStream())) { // 设置响应头,准备发送 ZIP 文件 prepareResponse(response, folderOrg.getName()); // 递归调用将子文件夹及其文件添加到 ZIP addFolderToZip(zipOutputStream, folderId, folderOrg.getName()); } catch (IOException e) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to download folder: " + e.getMessage()); } }

这里首先假设有一个目录:测试目录,里面有文件与嵌套文件目录。以下是针对递归文件目录打包ZIP下载实现的一个效果截图。 

 

设置响应头

基于上述代码,实现响应头的设置方法。在准备将文件打包成 ZIP 文件之前,需要设置 HTTP 响应的相关信息,包括字符编码、内容类型和文件名称。这将确保用户在下载时能够正确识别文件类型。

 

java

代码解读

复制代码

/** * 准备 HTTP 响应,设置响应头以便下载 ZIP 文件。 * * @param response HTTP 响应对象 * @param folderName 文件夹名称,用于生成 ZIP 文件的名称 * @throws IOException 在设置响应头时可能抛出异常 */ private void prepareResponse(HttpServletResponse response, String folderName) throws IOException { // 设置字符编码 response.setCharacterEncoding("UTF-8"); // 设置下载文件的名称,使用 URL 编码以兼容特殊字符 response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(folderName + ".zip", "UTF-8")); // 设置内容类型为 ZIP 文件 response.setContentType("application/zip"); }

递归添加文件夹及文件

基于上述代码,实现addFolderToZip方法是实现递归的关键。它首先获取当前文件夹中的文件列表,然后将这些文件添加到ZIP中。接着,它会获取当前文件夹的所有子文件夹,并对每个子文件夹递归调用自身。

 

java

代码解读

复制代码

/** * 递归处理文件夹及其子文件夹 * 1.首先获取当前文件夹的文件列表,并调用 addFilesToZip 方法将文件添加到 ZIP 中。 * 2.然后获取当前文件夹的子文件夹,并递归调用 addFolderToZip 方法处理每个子文件夹 * @param zipOutputStream ZipOutputStream * @param folderId 文件夹ID * @throws IOException IO异常 */ private void addFolderToZip(ZipOutputStream zipOutputStream, Integer folderId, String parentFolderName) throws IOException { // 获取当前文件夹的文件列表 List<FileOrg> fileOrgList = getFileBeansByFolderId(folderId); // 将当前文件夹的文件添加到 ZIP addFilesToZip(zipOutputStream, fileOrgList,parentFolderName); // 获取当前文件夹的子文件夹 List<FolderOrg> subFolders = getSubFoldersByFolderId(folderId); for (FolderOrg subFolder : subFolders) { // 递归调用将子文件夹及其文件列表添加到 ZIP addFolderToZip(zipOutputStream, subFolder.getId(),parentFolderName + "/" + subFolder.getName()); } }

获取子文件目录与文件列表

获取子文件夹与文件列表需根据自身业务实现,这里基于数据库查询子文件目录,查询文件目录下的文件,同时又涉及了一些处理业务逻辑。

1.获取当前文件夹的所有子文件夹

 

java

代码解读

复制代码

/** * 获取指定文件夹下的所有子文件夹。 * @param folderId 文件夹ID * @return List<FolderOrg> */ private List<FolderOrg> getSubFoldersByFolderId(Integer folderId) { QueryWrapper<FolderOrg> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("deleted",0).eq("parent_id", folderId); List<FolderOrg> folderOrgs = folderOrgMappr.selectList(queryWrapper); return folderOrgs; }

2.获取文件夹下的文件列表

 

java

代码解读

复制代码

/** * 根据文件夹 ID 获取该文件夹下的所有文件信息。 * * @param folderId 文件夹 ID * @return 文件组织列表,包含该文件夹下的所有文件信息 */ private List<FileOrg> getFileBeansByFolderId(Integer folderId) { // 创建查询条件,查找该文件夹下的所有文件链接 QueryWrapper<FileLinkOrg> queryWrapper1 = new QueryWrapper<>(); queryWrapper1.eq("folder_id", folderId); List<FileLinkOrg> fileLinkOrgList = fileLinkOrgMapper.selectList(queryWrapper1); // 如果没有文件,返回空列表 if (fileLinkOrgList.isEmpty()) { return new ArrayList<FileOrg>(0); } // 创建文件 ID 和名称的映射关系 HashMap<String, String> fileNameMap = new HashMap<>(); fileLinkOrgList.forEach(item -> fileNameMap.put(item.getFileId(), item.getFileName())); // 获取文件夹下所有文件的 ID ArrayList<String> fileIdList = new ArrayList<>(fileLinkOrgList.size()); fileLinkOrgList.forEach(item -> fileIdList.add(item.getFileId())); // 根据文件 ID 查询文件存储信息 QueryWrapper<FileOrg> queryWrapper2 = new QueryWrapper<>(); queryWrapper2.in("id", fileIdList); List<FileOrg> fileOrgList = fileOrgMapper.selectList(queryWrapper2); // 更新文件组织列表中的文件名称 fileOrgList.forEach(item -> item.setFileName(fileNameMap.get(item.getId()))); return fileOrgList; }

将文件添加到ZIP中

基于上述代码,实现addFilesToZip方法。需要将查询到的文件添加到 ZIP 输出流中。使用 ZipOutputStream 类来处理 ZIP 文件的创建和写入。在写入每个文件时,需要确保使用正确的路径和名称。

 

java

代码解读

复制代码

/** * 将指定文件列表中的文件添加到 ZIP 输出流中。 * * @param zipOutputStream ZIP 输出流 * @param fileOrgList 文件组织列表,包含待添加的文件信息 * @throws IOException 在处理输入输出时可能抛出异常 */ private void addFilesToZip(ZipOutputStream zipOutputStream, List<FileOrg> fileOrgList,String parentFolderName) throws IOException { // 遍历文件列表,将每个文件添加到 ZIP for (FileOrg fileOrg : fileOrgList) { try (InputStream inputStream = minioUtils.getObject(fileOrg.getBucketName(), fileOrg.getFilePath())) { // 设置 ZIP 条目的路径,包括文件夹名称 String zipEntryName = parentFolderName + "/" + fileOrg.getFileName(); // 创建 ZIP 条目,使用文件名称 zipOutputStream.putNextEntry(new ZipEntry(zipEntryName)); byte[] buffer = new byte[2048]; int length; // 读取文件内容并写入 ZIP 输出流 while ((length = inputStream.read(buffer)) > 0) { zipOutputStream.write(buffer, 0, length); } // 关闭当前 ZIP 条目 zipOutputStream.closeEntry(); } catch (Exception e) { // 记录异常信息,继续处理其他文件 log.info("-------------------- 打包ZIP下载异常: {}--------------------", e.getMessage()); } } }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值