fix: 优化压缩包解析逻辑
This commit is contained in:
parent
f7eb3a8ab7
commit
a6810efe79
@ -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();
|
||||
|
||||
@ -102,7 +151,7 @@ public class ZipFileUtil {
|
||||
|
||||
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<? 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) {
|
||||
if (entryName == null) return "";
|
||||
int lastSep = Math.max(entryName.lastIndexOf('/'), entryName.lastIndexOf('\\'));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user