fix: 优化压缩包解析逻辑
This commit is contained in:
parent
f7eb3a8ab7
commit
a6810efe79
@ -73,6 +73,55 @@ public class ZipFileUtil {
|
|||||||
return extractZipToTemp(file, getDefaultTempDir());
|
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 {
|
public static ZipContent extractZipToTemp(MultipartFile file, String baseTempDir) throws IOException {
|
||||||
ZipContent content = new ZipContent();
|
ZipContent content = new ZipContent();
|
||||||
|
|
||||||
@ -102,7 +151,7 @@ public class ZipFileUtil {
|
|||||||
|
|
||||||
for (Charset charset : charsets) {
|
for (Charset charset : charsets) {
|
||||||
try {
|
try {
|
||||||
content = extractFromZipFile(zipFile, tempDirPath.toFile(), charset);
|
content = extractExcelWithRelatedFiles(zipFile, tempDirPath.toFile(), charset);
|
||||||
content.tempDir = tempDirPath.toString();
|
content.tempDir = tempDirPath.toString();
|
||||||
return content;
|
return content;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -179,6 +228,134 @@ public class ZipFileUtil {
|
|||||||
return content;
|
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<? extends ZipEntry> 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) {
|
private static String getFileName(String entryName) {
|
||||||
if (entryName == null) return "";
|
if (entryName == null) return "";
|
||||||
int lastSep = Math.max(entryName.lastIndexOf('/'), entryName.lastIndexOf('\\'));
|
int lastSep = Math.max(entryName.lastIndexOf('/'), entryName.lastIndexOf('\\'));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user