SpringBoot中解压上传.tar.gz文件时保留原目录结构
解决方案:保留tar.gz目录结构并生成List
你的核心需求是让每个FileItem携带原始压缩包内的相对目录路径,这样后续处理时就能还原目录结构。关键在于利用TarArchiveEntry自带的路径信息,同时优化文件读取逻辑,具体修改如下:
修改后的代码
private List<FileItem> unTarFile(MultipartFile file) throws Exception{ List<FileItem> files = new ArrayList<>(); // 使用try-with-resources自动关闭流,避免资源泄漏 try (InputStream in = file.getInputStream(); GzipCompressorInputStream gzipIn = new GzipCompressorInputStream(in); TarArchiveInputStream tarIn = new TarArchiveInputStream(gzipIn)) { TarArchiveEntry entry; // 遍历压缩包内的所有条目 while ((entry = tarIn.getNextTarEntry()) != null) { // 跳过目录条目,只处理文件 if (entry.isDirectory()) { continue; } // entry.getName() 直接返回压缩包内文件的完整相对路径(如dir1/file1) String entryRelativePath = entry.getName(); String mimeType = URLConnection.guessContentTypeFromName(entryRelativePath); // 创建FileItem时,传入完整相对路径作为文件名 FileItem fileItem = new DiskFileItem( "fileData", mimeType, false, entryRelativePath, (int) entry.getSize(), null ); // 用缓冲区循环读取,避免大文件导致内存溢出 try (OutputStream out = fileItem.getOutputStream()) { byte[] buf = new byte[8192]; // 8KB缓冲区,可根据需求调整 int readBytes; while ((readBytes = tarIn.read(buf)) != -1) { out.write(buf, 0, readBytes); } } files.add(fileItem); } } return files; }
关键说明
- 保留目录路径:
TarArchiveEntry.getName()会直接返回文件在压缩包内的完整相对路径(比如dir2/file2),将这个路径作为DiskFileItem的文件名参数,每个FileItem就会携带原始目录结构信息。 - 跳过目录条目:压缩包内的目录本身不需要转为
FileItem,通过entry.isDirectory()判断后跳过即可,文件的路径信息已经足够还原目录结构。 - 优化读取逻辑:原代码一次性把整个文件读入内存,大文件场景下容易触发OOM,改用固定大小缓冲区循环读取更安全高效。
- 自动资源管理:使用try-with-resources语法,确保所有输入输出流自动关闭,避免资源泄漏问题。
后续还原目录结构示例
如果需要将这些FileItem写入磁盘并还原目录,只需根据FileItem.getName()的路径创建父目录即可:
// 目标根目录 String targetRootDir = "/your/target/directory"; for (FileItem item : files) { File targetFile = new File(targetRootDir, item.getName()); // 创建父目录(如果不存在) if (!targetFile.getParentFile().exists()) { targetFile.getParentFile().mkdirs(); } // 将FileItem写入目标文件 item.write(targetFile); }
内容的提问来源于stack exchange,提问作者user1971376
相关产品推荐
相关产品推荐

