避免 ZipArchive 文件在包含 .DS_Store 数据或 Unix 文件时出现“路径中的非法字符”错误
如果 Zip 文件源自 Linux 或 Mac,ZipArchive 类在尝试返回 Entries 集合时可能会失败
引言
这个辅助类允许从 ZipArchive 获取未经路径检查的原始 Entries 集合。
之后,你可以使用选定的有效条目进行解压或重命名,或者进行任何你想要的操作。
背景
ZipArchive 具有一个名为 Entries 的公共属性,它是对 Zip 文件中所有条目(文件名和目录)的唯一访问方式。
但是,ZipArchive 在返回条目集合之前,会内部使用 System.IO.Path.CheckInvalidPathChars 对所有条目进行检查。
当我们在处理来自 Mac 或 Linux 创建的 Zip 文件时,这些条目可能包含“.DS_Store”或其他在 Windows 中由于历史原因而无效的名称。
在这种情况下,ZipArchive 会在没有替代方案的情况下失败。
使用代码
这个简单的扩展,添加了一个 GetRawEntries() 方法来避免这个问题。
//
// Workaround Entries Collection in ZipArchive
// (C)2015 Ramon Ordiales
//
public static class ZipArchiveHelper
{
private static FieldInfo _Entries;
private static MethodInfo _EnsureDirRead;
static ZipArchiveHelper()
{
_Entries= typeof(ZipArchive).GetField("_entries",BindingFlags.NonPublic|BindingFlags.Instance);
_EnsureDirRead = typeof(ZipArchive).GetMethod("EnsureCentralDirectoryRead", BindingFlags.NonPublic | BindingFlags.Instance);
}
public static List<ZipArchiveEntry> GetRawEntries(this ZipArchive archive)
{
_EnsureDirRead.Invoke(archive, null);
return (List<ZipArchiveEntry>)_Entries.GetValue(archive);
}
}
关注点
“Private Static FieldInfo _Entries”是一个在启动时存储一次的变量。因此,使用这段代码不会产生性能影响。
ZipArchive 中的所有 Zip 条目在调用“Entries”之前就已经存在。它只是在额外进行路径检查的情况下暴露所有条目(我们想要避免的只是这个检查)。
历史
这个问题已经存在多年了,特别是对于非英语开发者和/或 Linux/Mac 原生 Zip 文件。
更新:在提取条目之前添加“EnsureCentralDirectoryRead”。