35

次のコードを使用して、フォルダー内のすべてのファイルを抽出しています

        using (ZipArchive archive = new ZipArchive(zipStream))
        {
            archive.ExtractToDirectory(location);
        }

ただし、1 つのファイルが存在する場合は、例外がスローされます。Compression API に既存のファイルを置き換えるように指示する方法はありますか。

最初にすべてのファイル名を取得してから、ファイルが存在するかどうかを確認して削除する方法が1つ見つかりました。しかし、これはどういうわけか私にとって非常に高価です。

4

11 に答える 11

62

拡張機能を作成しました。それを改善するためのコメントをいただければ幸いです。

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);
        }
    }
}
于 2013-02-10T07:40:48.557 に答える
20

このコードは、フォルダーが存在しない場合に例外をスローせず、フォルダーを作成します。

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);
        }
    }
}
于 2015-05-24T15:23:01.547 に答える
8

これを見てください:Creating zip files easy in .NET 4.5。あなたの問題は解決されたようです。または、 DotNetZipを確認することもできます。

于 2013-02-10T06:25:45.290 に答える
6

私はLinqの完全なファンなので、参考までにLinq風の方法を以下に示します。

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));
}
于 2018-06-21T08:50:02.210 に答える
5

ファイルを一時ディレクトリに抽出し、ovveride オプションを true に設定して「File.Copy」を使用してファイルを宛先ディレクトリにコピーできます。

私はそれが完璧な解決策ではないことを知っていますが、この方法ではファイルが存在するかどうかを確認する必要はありません

于 2013-02-10T06:32:09.160 に答える
0

すべてのフォルダーを作成するための回答から少し作り直した方法

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);
        if (file.Name == "")
        {// Assuming Empty for Directory
            Directory.CreateDirectory(Path.GetDirectoryName(completeFileName));
            continue;
        }
        // create dirs
        var dirToCreate = destinationDirectoryName;
        for (var i = 0; i < file.FullName.Split('/').Length - 1; i++)
        {
            var s = file.FullName.Split('/')[i];
            dirToCreate = Path.Combine(dirToCreate, s);
            if (!Directory.Exists(dirToCreate))
                Directory.CreateDirectory(dirToCreate);
        }
        file.ExtractToFile(completeFileName, true);
    }
}
于 2018-04-06T20:52:37.400 に答える