From a6810efe79b7e26cac4565f1cb2f9807e97c9558 Mon Sep 17 00:00:00 2001 From: tangwei Date: Thu, 7 May 2026 16:56:46 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E5=8E=8B=E7=BC=A9?= =?UTF-8?q?=E5=8C=85=E8=A7=A3=E6=9E=90=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yfd/platform/data/utils/ZipFileUtil.java | 187 +++++++++++++++++- 1 file changed, 182 insertions(+), 5 deletions(-) diff --git a/backend/src/main/java/com/yfd/platform/data/utils/ZipFileUtil.java b/backend/src/main/java/com/yfd/platform/data/utils/ZipFileUtil.java index 30fedc3..0fc4d34 100644 --- a/backend/src/main/java/com/yfd/platform/data/utils/ZipFileUtil.java +++ b/backend/src/main/java/com/yfd/platform/data/utils/ZipFileUtil.java @@ -73,6 +73,55 @@ public class ZipFileUtil { return extractZipToTemp(file, getDefaultTempDir()); } +// public static ZipContent extractZipToTemp(MultipartFile file, String baseTempDir) throws IOException { +// ZipContent content = new ZipContent(); +// +// String taskId = UUID.randomUUID().toString().substring(0, 8); +// Path tempDirPath = Paths.get(baseTempDir, "zip_" + taskId); +// +// log.info("extractZipToTemp: {}", tempDirPath); +// Files.createDirectories(tempDirPath); +// content.tempDir = tempDirPath.toString(); +// File zipFile = new File(tempDirPath.toFile(), "upload.zip"); +// file.transferTo(zipFile); +// +// try { +// log.info("--------------isValidZipFile------------"); +// if (!isValidZipFile(zipFile)) { +// log.info("--------------文件不是有效的ZIP格式或已损坏------------"); +// throw new IOException("文件不是有效的ZIP格式或已损坏"); +// } +// +// IOException lastException = null; +// Charset[] charsets = new Charset[]{ +// StandardCharsets.UTF_8, +// Charset.forName("GBK"), +// StandardCharsets.ISO_8859_1, +// Charset.forName("GB18030") +// }; +// +// for (Charset charset : charsets) { +// try { +// content = extractFromZipFile(zipFile, tempDirPath.toFile(), charset); +// content.tempDir = tempDirPath.toString(); +// return content; +// } catch (IOException e) { +// lastException = e; +// content = new ZipContent(); +// content.tempDir = tempDirPath.toString(); +// } +// } +// +// log.error("extractZipToTemp: {}", lastException.getMessage()); +// throw lastException != null ? lastException : new IOException("无法解析ZIP文件"); +// +// } finally { +// if (zipFile.exists()) { +// zipFile.delete(); +// } +// } +// } + public static ZipContent extractZipToTemp(MultipartFile file, String baseTempDir) throws IOException { ZipContent content = new ZipContent(); @@ -94,15 +143,15 @@ public class ZipFileUtil { IOException lastException = null; Charset[] charsets = new Charset[]{ - StandardCharsets.UTF_8, - Charset.forName("GBK"), - StandardCharsets.ISO_8859_1, - Charset.forName("GB18030") + StandardCharsets.UTF_8, + Charset.forName("GBK"), + StandardCharsets.ISO_8859_1, + Charset.forName("GB18030") }; for (Charset charset : charsets) { try { - content = extractFromZipFile(zipFile, tempDirPath.toFile(), charset); + content = extractExcelWithRelatedFiles(zipFile, tempDirPath.toFile(), charset); content.tempDir = tempDirPath.toString(); return content; } catch (IOException e) { @@ -179,6 +228,134 @@ public class ZipFileUtil { return content; } + + private static ZipContent extractExcelWithRelatedFiles(File zipFile, File tempDir, Charset charset) throws IOException { + ZipContent content = new ZipContent(); + + try (ZipFile zip = new ZipFile(zipFile, charset)) { + Enumeration entries = zip.entries(); + + String excelEntryName = null; + String excelParentPath = null; + + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + String entryName = entry.getName(); + + if (entry.isDirectory()) { + continue; + } + + String lowerName = entryName.toLowerCase(); + if ((lowerName.endsWith(".xlsx") || lowerName.endsWith(".xls")) && excelEntryName == null) { + excelEntryName = entryName; + excelParentPath = getParentDirectory(entryName); + log.info("找到Excel文件: {}, 所在目录: {}", excelEntryName, excelParentPath); + break; + } + } + + if (excelEntryName == null) { + throw new IOException("ZIP文件中未找到Excel文件(.xlsx或.xls)"); + } + + entries = zip.entries(); + int excelCount = 0; + int imageCount = 0; + int videoCount = 0; + + while (entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + String entryName = entry.getName(); + + if (entry.isDirectory()) { + continue; + } + + String entryParentPath = getParentDirectory(entryName); + String fileName = getFileName(entryName); + String lowerName = entryName.toLowerCase(); + + boolean shouldExtract = false; + String targetSubFolder = ""; + + if (lowerName.endsWith(".xlsx") || lowerName.endsWith(".xls")) { + if (excelParentPath.equals(entryParentPath)) { + shouldExtract = true; + targetSubFolder = ""; + } + } else if (isInSubDirectory(entryParentPath, excelParentPath, "images")) { + if (isImageFile(lowerName)) { + shouldExtract = true; + targetSubFolder = "images"; + } + } else if (isInSubDirectory(entryParentPath, excelParentPath, "videos")) { + if (isVideoFile(lowerName)) { + shouldExtract = true; + targetSubFolder = "videos"; + } + } + + if (shouldExtract) { + try (InputStream is = zip.getInputStream(entry)) { + String filePath = saveFileToDir(is, tempDir, targetSubFolder, fileName); + + if (targetSubFolder.isEmpty()) { + if (content.excelFilePath == null) { + content.excelFileName = fileName; + content.excelFilePath = filePath; + excelCount++; + log.info("提取Excel文件: {}", fileName); + } + } else if ("images".equals(targetSubFolder)) { + content.images.put(fileName, filePath); + imageCount++; + log.debug("提取图片文件: {}", fileName); + } else if ("videos".equals(targetSubFolder)) { + content.videos.put(fileName, filePath); + videoCount++; + log.debug("提取视频文件: {}", fileName); + } + } + } + } + + if (content.excelFilePath == null) { + throw new IOException("未能提取到Excel文件"); + } + + log.info("提取完成 - Excel: {}个, 图片: {}个, 视频: {}个", + excelCount, imageCount, videoCount); + } + + return content; + } + + private static String getParentDirectory(String entryName) { + if (entryName == null || entryName.isEmpty()) { + return ""; + } + int lastSep = Math.max(entryName.lastIndexOf('/'), entryName.lastIndexOf('\\')); + if (lastSep >= 0) { + return entryName.substring(0, lastSep); + } + return ""; + } + + private static boolean isInSubDirectory(String entryParentPath, String excelParentPath, String subFolder) { + String expectedPath; + if (excelParentPath.isEmpty()) { + expectedPath = subFolder; + } else { + expectedPath = excelParentPath + "/" + subFolder; + } + + String normalizedEntryPath = entryParentPath.replace("\\", "/"); + String normalizedExpectedPath = expectedPath.replace("\\", "/"); + + return normalizedEntryPath.equalsIgnoreCase(normalizedExpectedPath); + } + private static String getFileName(String entryName) { if (entryName == null) return ""; int lastSep = Math.max(entryName.lastIndexOf('/'), entryName.lastIndexOf('\\'));