当ZipArchive包含非法字符时,如何获得ZipArchive的有效条目?

时间:2017-02-15 23:23:34

标签: c# .net ziparchive argumentexception illegal-characters

我正在使用System.IO.Compression来提取一些Zip文件的内容。问题是,只要存在包含某些Windows非法字符的文件名的条目,就会抛出异常。我已经尝试了几件事,但我仍然没有找到任何方法来忽略不良条目并提取那些好的条目。请注意,修改zip文件的内容不是我们正在执行的处理类型的可能性,因此我必须按原样处理该文件。

系统通常处理包含多个条目的文件,这个数字是可变的,但在一个zip文件中最多可以有300个条目,偶尔会有一个带有'myfile<name>.txt'等文件名的条目,其中包含尖括号,对于Windows来说显然是非法字符。我真的想忽略这个条目,然后继续提取ZipArchive中的其余条目。但看起来这是不可能的。

如何忽视ZipArchive的错误条目?

到目前为止,我已经尝试了不同的东西来单独获取条目,但我总是得到完全相同的异常错误。

以下是我到目前为止尝试过的一些事情:

  • 实现迭代条目的常规方式:

    foreach (ZipArchiveEntry entry in ZipArchive.Entries)
    
  • 尝试通过索引只获取一个条目(即使第一个条目是有效条目,此处也是相同的异常):

    ZipArchiveEntry entry = ZipArchive.Entries[0]
    
  • 使用lambda表达式应用过滤器来忽略无效的条目(同样的例外):

    var entries = zipArchive.Entries.Where(a => 
    a.FullName.IndexOfAny(Path.GetInvalidFileNameChars() ) == -1);
    

这没有任何帮助,每次我得到的例外情况如下:

  

at System.IO.Path.CheckInvalidPathChars(String path,Boolean   checkAdditional)在System.IO.Path.GetFileName(String path)at   System.IO.Compression.ZipHelper.EndsWithDirChar(String test)at   System.IO.Compression.ZipArchiveEntry.set_FullName(String value)at   System.IO.Compression.ZipArchiveEntry..ctor(ZipArchive archive,   ZipCentralDirectoryFileHeader cd)at   System.IO.Compression.ZipArchive.ReadCentralDirectory()at   System.IO.Compression.ZipArchive.get_Entries()at   ZipLibraryConsole.MicrosoftExtraction.RecursiveExtract(流   fileToExtract,Int32 maxDepthLevel,Attachment att)in   C:\ Users \ myUser \ Documents \ Visual Studio   2015年\项目\ ZipLibraryConsole \ ZipLibraryConsole \ MicrosoftExtraction.cs:行   47

这是已实现代码的片段:

var zipArchive = new ZipArchive(fileToExtract, ZipArchiveMode.Read);
  try
    {
      foreach (var zipEntry in zipArchive.Entries) // the exception is thrown  here, there is no chance to process valid entries at all
      {
        // Do something and extract the file
      }
    catch (ArgumentException exception)
    {
      Console.WriteLine(
        String.Format("Failed to complete the extraction. At least one path contains invalid characters for the Operating System: {0}{1}",                       att.Name, att.Extention));
     }

1 个答案:

答案 0 :(得分:0)

使用System.Reflection,您至少可以隐藏错误,尽管您最多只能获得条目中包含非法字符路径的条目。

添加此类并使用archive.GetRawEntries()而不是archive.Entries

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)
    {
        try { _EnsureDirRead.Invoke(archive, null); } catch { }
        return (List<ZipArchiveEntry>)_Entries.GetValue(archive);
    }
}

try-catch很丑陋,如果它使您感到烦恼,则可以捕获特定的异常。 根据上面的评论,此问题已在.NET Core中修复。 (更新:确认此问题已在.Net Core 3.1中修复,也许更早了。)

此{部分}修复对https://www.codeproject.com/Tips/1007398/Avoid-Illegal-Characters-in-Path-error-in-ZipArchihttps://gist.github.com/rdavisau/b66df9c99a4b11c5ceff的信用

更多有关在ZipFile.ExtractToDirectory "Illegal characters in path"处使用非法字符(不仅仅是zip文件)修复路径的指针