|
|
@@ -6,9 +6,13 @@ import com.fdkankan.contro.constant.ZipConstant;
|
|
|
import net.lingala.zip4j.ZipFile;
|
|
|
import net.lingala.zip4j.model.FileHeader;
|
|
|
|
|
|
+import java.io.File;
|
|
|
import java.io.InputStream;
|
|
|
+import java.nio.charset.Charset;
|
|
|
import java.nio.file.Paths;
|
|
|
+import java.util.Enumeration;
|
|
|
import java.util.List;
|
|
|
+import java.util.zip.ZipEntry;
|
|
|
|
|
|
public class ZipUtil {
|
|
|
|
|
|
@@ -36,4 +40,65 @@ public class ZipUtil {
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解压 zip 压缩包到目标目录
|
|
|
+ * @param zipFilePath 压缩包路径
|
|
|
+ * @param destDirPath 解压目录
|
|
|
+ */
|
|
|
+ public static void unzip(String zipFilePath, String destDirPath) {
|
|
|
+ File zipFile = new File(zipFilePath);
|
|
|
+ File destDir = new File(destDirPath);
|
|
|
+
|
|
|
+ // 自动检测编码,常见 GBK / UTF-8
|
|
|
+ Charset charset = detectCharset(zipFile);
|
|
|
+
|
|
|
+ // 解压(如果是 Windows 打包的 zip,GBK 最常见)
|
|
|
+ cn.hutool.core.util.ZipUtil.unzip(zipFile, destDir, charset);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检测 ZIP 文件的编码(仅用于文件名编码判断)
|
|
|
+ * 逻辑:UTF-8 -> GBK -> default
|
|
|
+ * @param zipFile ZIP 文件
|
|
|
+ * @return Charset 识别到的编码
|
|
|
+ */
|
|
|
+ public static Charset detectCharset(File zipFile) {
|
|
|
+ // 1. 尝试 UTF-8
|
|
|
+ if (isCharset(zipFile, Charset.forName("UTF-8"))) {
|
|
|
+ return Charset.forName("UTF-8");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 尝试 GBK(Windows zip 默认编码)
|
|
|
+ if (isCharset(zipFile, Charset.forName("GBK"))) {
|
|
|
+ return Charset.forName("GBK");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 都不行 → 返回系统默认
|
|
|
+ return Charset.defaultCharset();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 判断使用该编码读取 ZIP 是否正常(没有乱码字符)
|
|
|
+ */
|
|
|
+ private static boolean isCharset(File zipFile, Charset charset) {
|
|
|
+ try (java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFile, charset)) {
|
|
|
+ Enumeration<? extends ZipEntry> entries = zf.entries();
|
|
|
+ while (entries.hasMoreElements()) {
|
|
|
+ ZipEntry entry = entries.nextElement();
|
|
|
+
|
|
|
+ // 只检查名字,不读取内容
|
|
|
+ String name = entry.getName();
|
|
|
+
|
|
|
+ // 若名字中出现 �(替换字符),说明编码不对
|
|
|
+ if (name.contains("\uFFFD")) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ } catch (Exception e) {
|
|
|
+ // 出现异常说明该编码不匹配
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|