wangzaijun před 2 měsíci
rodič
revize
df7fca03bf

+ 0 - 0
mo-daq/logs/error.log


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 71 - 0
mo-daq/logs/info.log


+ 2 - 0
mo-daq/logs/warn.log

@@ -0,0 +1,2 @@
+2025-02-28 17:25:25.432 [HikariCP-daq housekeeper] - [] WARN  com.zaxxer.hikari.pool.HikariPool:797  - HikariCP-daq - Thread starvation or clock leap detected (housekeeper delta=3m39s364ms679µs500ns).
+2025-02-28 17:26:14.671 [HikariCP-daq housekeeper] - [] WARN  com.zaxxer.hikari.pool.HikariPool:797  - HikariCP-daq - Thread starvation or clock leap detected (housekeeper delta=49s238ms51µs100ns).

+ 6 - 3
mo-daq/src/main/java/com/smppw/modaq/domain/service/EmailParseService.java

@@ -46,6 +46,8 @@ import org.springframework.util.StopWatch;
 
 import java.io.File;
 import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.*;
 import java.util.regex.Matcher;
@@ -206,9 +208,10 @@ public class EmailParseService {
     }
 
     private String getDestinationPath(String filepath, String extension) {
-        String fileName = Paths.get(filepath).getFileName().toString();
+        Path path = Paths.get(filepath);
+        String fileName = path.getFileName().toString();
         String baseName = fileName.substring(0, fileName.length() - extension.length());
-        return Paths.get(filepath).getParent().resolve(baseName).toString();
+        return path.getParent().resolve(baseName).toString();
     }
 
     public void saveRelatedTable(String emailKey, String emailAddress,
@@ -486,7 +489,7 @@ public class EmailParseService {
                     saveFile.setReadable(true);
                     if (!saveFile.exists()) {
                         if (!saveFile.getParentFile().exists()) {
-                            saveFile.getParentFile().mkdirs();
+                            Files.createDirectories(saveFile.getParentFile().toPath());
                             saveFile.getParentFile().setExecutable(true);
                         }
                     }

+ 67 - 45
mo-daq/src/main/java/com/smppw/modaq/infrastructure/util/ExcelUtil.java

@@ -5,6 +5,7 @@ import cn.hutool.core.collection.ListUtil;
 import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.util.StrUtil;
 import com.github.junrar.Archive;
+import com.github.junrar.exception.RarException;
 import com.github.junrar.rarfile.FileHeader;
 import org.apache.commons.compress.archivers.ArchiveEntry;
 import org.apache.commons.compress.archivers.ArchiveException;
@@ -12,12 +13,14 @@ import org.apache.commons.compress.archivers.ArchiveInputStream;
 import org.apache.commons.compress.archivers.ArchiveStreamFactory;
 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
 import org.apache.commons.compress.archivers.zip.ZipFile;
-import org.apache.commons.compress.utils.IOUtils;
+import org.apache.commons.io.IOUtils;
 
 import java.io.*;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.List;
@@ -46,35 +49,37 @@ public class ExcelUtil {
     public static List<String> extractCompressedFiles(String zipFilePath, String destFilePath) throws IOException, ArchiveException {
         List<String> filePathList = CollUtil.newArrayList();
 
-        File destFile = FileUtil.file(destFilePath);
+        File destFile = FileUtil.file(destFilePath).getCanonicalFile();
         if (!destFile.exists()) {
-            destFile.mkdirs();
+            Files.createDirectories(destFile.toPath());
         }
 
-
         try (BufferedInputStream fis = new BufferedInputStream(new FileInputStream(zipFilePath));
-             ArchiveInputStream ais = new ArchiveStreamFactory().createArchiveInputStream(fis)) {
+             ArchiveInputStream<? extends ArchiveEntry> ais = new ArchiveStreamFactory("UTF-8")
+                     .createArchiveInputStream(ArchiveStreamFactory.ZIP, fis)) {
             ArchiveEntry entry;
             int i = 1;
             while ((entry = ais.getNextEntry()) != null) {
+                // 跳过不可读条目(如加密文件)
+                if (!ais.canReadEntryData(entry)) {
+                    continue;
+                }
                 String name = entry.getName();
-                File entryFile;
-                try {
-                    entryFile = FileUtil.file(destFilePath, name);
-                } catch (Exception e) {
-                    String zipFilename = FileUtil.getName(destFilePath);
-                    String ext = FileUtil.extName(name);
-                    name = zipFilename + "_" + i + "." + ext;
-                    entryFile = FileUtil.file(destFilePath, name);
-                    i++;
+                File entryFile = FileUtil.file(destFilePath, name);
+
+                // 安全检查
+                if (!entryFile.toPath().normalize().startsWith(destFile.toPath())) {
+                    throw new IOException("非法路径: " + name);
                 }
+
                 if (entry.isDirectory()) {
-                    entryFile.mkdirs();
+                    Files.createDirectories(entryFile.toPath());
                 } else {
-                    try (FileOutputStream fos = new FileOutputStream(entryFile)) {
+                    Files.createDirectories(entryFile.getParentFile().toPath());
+                    try (OutputStream fos = Files.newOutputStream(entryFile.toPath())) {
                         IOUtils.copy(ais, fos);
-                        filePathList.add(entryFile.getPath());
                     }
+                    filePathList.add(entryFile.getPath());
                 }
             }
         } catch (Exception e) {
@@ -90,44 +95,61 @@ public class ExcelUtil {
         return filePathList;
     }
 
-    public static List<String> extractRar(String inputFilePath, String outputDirPath) {
+    public static List<String> extractRar(String inputFilePath, String outputDirPath) throws IOException {
         List<String> fileList = new ArrayList<>();
-        // 创建Archive对象,用于读取rar压缩文件格式
-        try {
-            String zipFilename = FileUtil.getName(inputFilePath);
-            Archive archive = new Archive(new FileInputStream(inputFilePath));
-            // 读取压缩文件中的所有子目录或子文件(FileHeader对象)
-            List<FileHeader> fileHeaderList = archive.getFileHeaders();
-            int i = 1;
-            // 遍历子目录和子文件
-            for (FileHeader fd : fileHeaderList) {
-                String fileName = fd.getFileName();
-                String ext = FileUtil.extName(fileName);
-                fileName = zipFilename + "_" + i + "." + ext;
-                i++;
-                File f = FileUtil.file(outputDirPath + File.separator + fileName);
-                if (fd.isDirectory()) {
-                    // 创建新子目录
-                    f.mkdirs();
-                } else {
-                    // 创建新子文件
-                    f.createNewFile();
-                    // 获取压缩包中的子文件输出流
-                    InputStream in = archive.getInputStream(fd);
-                    // 复制文件输入流至新子文件
-                    FileUtil.copyFile(in, f);
-                    fileList.add(f.getAbsolutePath());
+        Path outputPath = Paths.get(outputDirPath).toRealPath();
+
+        try (FileInputStream fis = new FileInputStream(inputFilePath);
+             Archive archive = new Archive(fis)) {  // 假设Archive支持try-with-resources
+
+            for (FileHeader entry : archive.getFileHeaders()) {
+                // 跳过目录条目(由文件创建逻辑自动生成目录)
+                if (entry.isDirectory()) continue;
+
+                // 处理文件名编码和路径
+                String fileName = new String(entry.getFileNameByteArray(), StandardCharsets.UTF_8);
+                Path targetPath = outputPath.resolve(fileName).normalize();
+
+                // 路径安全检查
+                if (!targetPath.startsWith(outputPath)) {
+                    throw new IOException("检测到非法路径: " + fileName);
+                }
+
+                // 创建父目录
+                Files.createDirectories(targetPath.getParent());
+
+                // 处理文件重名
+                targetPath = resolveDuplicate(targetPath);
+
+                // 解压文件内容
+                try (InputStream entryStream = archive.getInputStream(entry)) {
+                    Files.copy(entryStream, targetPath, StandardCopyOption.REPLACE_EXISTING);
+                    fileList.add(targetPath.toAbsolutePath().toString());
                 }
             }
-        } catch (Exception e) {
+        } catch (UnsupportedEncodingException | RarException e) {
+            throw new IOException("解析RAR文件失败", e);
         }
         return fileList;
     }
 
+    private static Path resolveDuplicate(Path path) {
+        if (!Files.exists(path)) return path;
+        String base = path.getFileName().toString();
+        String name = base.replaceFirst("[.][^.]+$", "");
+        String ext = base.substring(name.length());
+        int counter = 1;
+        while (true) {
+            Path newPath = path.resolveSibling(name + "_" + counter + ext);
+            if (!Files.exists(newPath)) return newPath;
+            counter++;
+        }
+    }
+
     public static List<String> extractSplitZip(String zipFilePath, String destFilePath) throws IOException {
         List<String> resultList = ListUtil.list(false);
         File file = new File(zipFilePath);
-        try (ZipFile zipFile = new ZipFile(file)) {
+        try (ZipFile zipFile = ZipFile.builder().setFile(file).get()) {
             Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
             while (entries.hasMoreElements()) {
                 ZipArchiveEntry entry = entries.nextElement();