使用System.IO.Compression在提取文件期间强制替换现有文件?

use*_*567 22 c#

我使用以下代码来提取文件夹中的所有文件

        using (ZipArchive archive = new ZipArchive(zipStream))
        {
            archive.ExtractToDirectory(location);
        }
Run Code Online (Sandbox Code Playgroud)

但如果存在一个文件,则会抛出异常.是否有任何方法可以告诉Compression API替换现有文件.

我发现一种方法是首先获取所有文件名,然后检查文件是否存在并删除它.但这对我来说是非常昂贵的.

use*_*567 51

我创建了一个扩展.任何评论改进将不胜感激,

public static class ZipArchiveExtensions
{
    public static void ExtractToDirectory(this ZipArchive archive, string destinationDirectoryName, bool overwrite)
    {
        if (!overwrite)
        {
            archive.ExtractToDirectory(destinationDirectoryName);
            return;
        }

        DirectoryInfo di = Directory.CreateDirectory(destinationDirectoryName);
        string destinationDirectoryFullPath = di.FullName;

        foreach (ZipArchiveEntry file in archive.Entries)
        {
            string completeFileName = Path.GetFullPath(Path.Combine(destinationDirectoryFullPath, file.FullName));

            if (!completeFileName.StartsWith(destinationDirectoryFullPath, StringComparison.OrdinalIgnoreCase))
            {
                throw new IOException("Trying to extract file outside of destination directory. See this link for more info: https://snyk.io/research/zip-slip-vulnerability");
            }

            if (file.Name == "")
            {// Assuming Empty for Directory
                Directory.CreateDirectory(Path.GetDirectoryName(completeFileName));
                continue;
            }
            file.ExtractToFile(completeFileName, true);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Moh*_*y66 16

当文件夹不存在时,此代码不会抛出异常,而是创建文件夹.

public static class ZipArchiveExtensions
{
    public static void ExtractToDirectory(this ZipArchive archive, string destinationDirectoryName, bool overwrite)
    {
        if (!overwrite)
        {
            archive.ExtractToDirectory(destinationDirectoryName);
            return;
        }
        foreach (ZipArchiveEntry file in archive.Entries)
        {
            string completeFileName = Path.Combine(destinationDirectoryName, file.FullName);
            string directory = Path.GetDirectoryName(completeFileName);

            if (!Directory.Exists(directory))
                Directory.CreateDirectory(directory);

            if (file.Name != "")
                file.ExtractToFile(completeFileName, true);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 不要复制猫 (4认同)
  • JABFreeware,正如@ user960567所说的那样"对它的任何评论都会有所改进,我会赞赏它,"我只是添加几行来防止抛出异常!if(!Directory.Exists(directory))Directory.CreateDirectory(directory); (2认同)
  • 这是比公认的答案更强大的解决方案。谢谢。 (2认同)

小智 8

看看这个:在.NET 4.5中轻松创建zip文件.你的问题似乎得到了解决.或者,您也可以查看DotNetZip.


小智 7

从 .NET Standard 2.1 开始,它就像overwriteFiles在以下位置设置为 true 一样简单: ZipFile.ExtractToDirectory(string sourceFile, string destDir, Encoding entryNameEncoding, bool overwriteFiles)

Example:
ZipFile.ExtractToDirectory("c:\\file.zip","c:\\destination_folder", Encoding.UTF8, true);
Run Code Online (Sandbox Code Playgroud)

  • 这仅适用于 .NET Core,不适用于 .NET Framework,仅供参考 (6认同)
  • 据我所知,“ExtractToDictionary”是否不采用布尔值来允许覆盖 (2认同)

Fas*_*ack 6

由于我是 Linq 的忠实粉丝,Linq-ish 方式仅供参考:

using (var strm = File.OpenRead(zipPath))
using (ZipArchive a = new ZipArchive(strm))
{
    a.Entries.Where(o => o.Name == string.Empty && !Directory.Exists(Path.Combine(basePath, o.FullName))).ToList().ForEach(o => Directory.CreateDirectory(Path.Combine(basePath, o.FullName)));
    a.Entries.Where(o => o.Name != string.Empty).ToList().ForEach(e => e.ExtractToFile(Path.Combine(basePath, e.FullName), true));
}
Run Code Online (Sandbox Code Playgroud)


Gre*_*zik 5

您可以将文件解压缩到某个临时目录,然后使用“File.Copy”和 ovveride 选项将文件复制到您的目标目录

我知道这不是一个完美的解决方案,但是这样您就不需要检查文件是否存在


Nei*_*l B 5

这是一个获取 zip 文件路径的方法。

基于已接受的答案。

    public void ExtractZipFileToDirectory(string sourceZipFilePath, string destinationDirectoryName, bool overwrite)
    {
        using (var archive = ZipFile.Open(sourceZipFilePath, ZipArchiveMode.Read))
        {
            if (!overwrite)
            {
                archive.ExtractToDirectory(destinationDirectoryName);
                return;
            }

            DirectoryInfo di = Directory.CreateDirectory(destinationDirectoryName);
            string destinationDirectoryFullPath = di.FullName;

            foreach (ZipArchiveEntry file in archive.Entries)
            {
                string completeFileName = Path.GetFullPath(Path.Combine(destinationDirectoryFullPath, file.FullName));

                if (!completeFileName.StartsWith(destinationDirectoryFullPath, StringComparison.OrdinalIgnoreCase))
                {
                    throw new IOException("Trying to extract file outside of destination directory. See this link for more info: https://snyk.io/research/zip-slip-vulnerability");
                }

                if (file.Name == "")
                {// Assuming Empty for Directory
                    Directory.CreateDirectory(Path.GetDirectoryName(completeFileName));
                    continue;
                }
                file.ExtractToFile(completeFileName, true);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)