65.9K
CodeProject 正在变化。 阅读更多。
Home

避免 ZipArchive 文件在包含 .DS_Store 数据或 Unix 文件时出现“路径中的非法字符”错误

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (1投票)

2015年7月7日

CPOL
viewsIcon

12380

如果 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”。

 

© . All rights reserved.