Java文件目錄下載并打包成ZIP壓縮包
在Java中如果要實現(xiàn)文件夾、文件目錄的遞歸下載并打包成ZIP壓縮包,可以通過以下步驟進行:
遍歷文件夾:使用遞歸方法遍歷指定目錄下的所有文件和文件夾
創(chuàng)建ZIP輸出流:使用java.util.zip包中的ZipOutputStream類創(chuàng)建ZIP文件
將文件添加到ZIP:將遍歷到的文件逐個添加到ZIP壓縮包中
單個文件目錄打包ZIP下載
單個文件目錄打包ZIP下載與文件目錄遞歸打包ZIP下載類似,首先來看看單個文件目錄中的文件是如何打包ZIP下載的。
/** * 下載指定文件夾及其所有文件的內(nèi)容,并將其打包為 ZIP 文件。 * * @param folderId 需要下載的文件夾 ID * @param response HTTP 響應對象,用于發(fā)送 ZIP 文件 * @throws IOException 在處理輸入輸出時可能拋出異常 */ public void downloadFolder(Integer folderId, HttpServletResponse response) throws IOException { // 校驗權限,檢查用戶是否有權限下載該文件夾 Boolean isAuth = checkAuthService.checkAuthDownload(folderId); if (!isAuth) { // 如果沒有權限,則拋出業(yè)務異常 throw new BusinessException(TipsConstant.Tips_6002); } // 查詢指定文件夾下的所有文件列表 List<FileOrg> fileOrgList = getFileBeansByFolderId(folderId); // 獲取文件夾信息,用于設置 ZIP 文件的名稱 FolderOrg folderOrg = folderOrgMappr.selectById(folderId); // 準備壓縮文件的數(shù)據(jù) try (ZipOutputStream zipOutputStream = new ZipOutputStream(response.getOutputStream())) { // 設置響應頭,準備發(fā)送 ZIP 文件 prepareResponse(response, folderOrg.getName()); // 將文件添加到 ZIP 壓縮包中 addFilesToZip(zipOutputStream, fileOrgList, folderOrg.getName()); } catch (IOException e) { // 如果發(fā)生錯誤,返回 500 錯誤和錯誤信息 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to download folder: " + e.getMessage()); } }
這里首先假設有一個目錄:測試目錄,里面有文件與文件目錄。以下是針對單個文件目錄打包ZIP下載實現(xiàn)的一個效果截圖。
遞歸文件目錄打包ZIP下載
遞歸文件目錄打包ZIP下載相比單個文件目錄打包ZIP下載,無非是多了個遞歸文件目錄的操作。
@Override public void recursiveDownload(Integer folderId, HttpServletResponse response) throws IOException { // 校驗權限,檢查用戶是否有權限下載該文件夾 Boolean isAuth = checkAuthService.checkAuthDownload(folderId); if (!isAuth) { // 如果沒有權限,則拋出業(yè)務異常 throw new BusinessException(TipsConstant.Tips_6002); } // 獲取文件夾信息,用于設置 ZIP 文件的名稱 FolderOrg folderOrg = folderOrgMappr.selectById(folderId); // 準備壓縮文件的數(shù)據(jù) try (ZipOutputStream zipOutputStream = new ZipOutputStream(response.getOutputStream())) { // 設置響應頭,準備發(fā)送 ZIP 文件 prepareResponse(response, folderOrg.getName()); // 遞歸調(diào)用將子文件夾及其文件添加到 ZIP addFolderToZip(zipOutputStream, folderId, folderOrg.getName()); } catch (IOException e) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to download folder: " + e.getMessage()); } }
這里首先假設有一個目錄:測試目錄,里面有文件與嵌套文件目錄。以下是針對遞歸文件目錄打包ZIP下載實現(xiàn)的一個效果截圖。
設置響應頭
基于上述代碼,實現(xiàn)響應頭的設置方法。在準備將文件打包成 ZIP 文件之前,需要設置 HTTP 響應的相關信息,包括字符編碼、內(nèi)容類型和文件名稱。這將確保用戶在下載時能夠正確識別文件類型。
/** * 準備 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")); // 設置內(nèi)容類型為 ZIP 文件 response.setContentType("application/zip"); }
遞歸添加文件夾及文件
基于上述代碼,實現(xiàn)addFolderToZip方法是實現(xiàn)遞歸的關鍵。它首先獲取當前文件夾中的文件列表,然后將這些文件添加到ZIP中。接著,它會獲取當前文件夾的所有子文件夾,并對每個子文件夾遞歸調(diào)用自身。
/** * 遞歸處理文件夾及其子文件夾 * 1.首先獲取當前文件夾的文件列表,并調(diào)用 addFilesToZip 方法將文件添加到 ZIP 中。 * 2.然后獲取當前文件夾的子文件夾,并遞歸調(diào)用 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) { // 遞歸調(diào)用將子文件夾及其文件列表添加到 ZIP addFolderToZip(zipOutputStream, subFolder.getId(),parentFolderName + "/" + subFolder.getName()); } }
獲取子文件目錄與文件列表
獲取子文件夾與文件列表需根據(jù)自身業(yè)務實現(xiàn),這里基于數(shù)據(jù)庫查詢子文件目錄,查詢文件目錄下的文件,同時又涉及了一些處理業(yè)務邏輯。
1.獲取當前文件夾的所有子文件夾
/** * 獲取指定文件夾下的所有子文件夾。 * @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.獲取文件夾下的文件列表
/** * 根據(jù)文件夾 ID 獲取該文件夾下的所有文件信息。 * * @param folderId 文件夾 ID * @return 文件組織列表,包含該文件夾下的所有文件信息 */ private List<FileOrg> getFileBeansByFolderId(Integer folderId) { // 創(chuàng)建查詢條件,查找該文件夾下的所有文件鏈接 QueryWrapper<FileLinkOrg> queryWrapper1 = new QueryWrapper<>(); queryWrapper1.eq("folder_id", folderId); List<FileLinkOrg> fileLinkOrgList = fileLinkOrgMapper.selectList(queryWrapper1); // 如果沒有文件,返回空列表 if (fileLinkOrgList.isEmpty()) { return new ArrayList<FileOrg>(0); } // 創(chuàng)建文件 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())); // 根據(jù)文件 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中
基于上述代碼,實現(xiàn)addFilesToZip方法。需要將查詢到的文件添加到 ZIP 輸出流中。使用 ZipOutputStream 類來處理 ZIP 文件的創(chuàng)建和寫入。在寫入每個文件時,需要確保使用正確的路徑和名稱。
/** * 將指定文件列表中的文件添加到 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(); // 創(chuàng)建 ZIP 條目,使用文件名稱 zipOutputStream.putNextEntry(new ZipEntry(zipEntryName)); byte[] buffer = new byte[2048]; int length; // 讀取文件內(nèi)容并寫入 ZIP 輸出流 while ((length = inputStream.read(buffer)) > 0) { zipOutputStream.write(buffer, 0, length); } // 關閉當前 ZIP 條目 zipOutputStream.closeEntry(); } catch (Exception e) { // 記錄異常信息,繼續(xù)處理其他文件 log.info("-------------------- 打包ZIP下載異常: {}--------------------", e.getMessage()); } } }
到此這篇關于Java文件目錄下載并打包成ZIP壓縮包的文章就介紹到這了,更多相關Java文件目錄下載內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java接口和抽象類實現(xiàn)抽象和多態(tài)的方法示例
接口和抽象類是 Java 中兩種實現(xiàn)抽象和多態(tài)的方法。它們之間有一些區(qū)別,但也有一些相似之處。這一節(jié)我們將通過詳細的例子來更深入地了解接口和抽象類2023-05-05Java中的信息摘要算法MessageDigest類用法詳解
這篇文章主要介紹了Java中的信息摘要算法MessageDigest類用法詳解,java.security.MessageDigest類為應用程序提供信息摘要算法的功能,如MD5或SHA-1或SHA-256算法,信息摘要是安全的單向哈希函數(shù),它接收任意大小的數(shù)據(jù),并輸出固定長度的哈希值,需要的朋友可以參考下2024-01-01jvm細節(jié)探索之synchronized及實現(xiàn)問題分析
這篇文章主要介紹了jvm細節(jié)探索之synchronized及實現(xiàn)問題分析,涉及synchronized的字節(jié)碼表示,JVM中鎖的優(yōu)化,對象頭的介紹等相關內(nèi)容,具有一定借鑒價值,需要的朋友可以參考下。2017-11-11java發(fā)送heartbeat心跳包(byte轉(zhuǎn)16進制)
這篇文章主要介紹了java發(fā)送heartbeat心跳包(byte轉(zhuǎn)16進制),需要的朋友可以參考下2014-05-05