从包含zip的流中提取文件

时间:2020-01-08 20:01:25

标签: c# .net .net-core

我正在使用HttpClient发出GET请求,以从互联网下载一个zip文件。 我想提取zip文件中包含的所有文件,而不将zip文件保存到磁盘。 目前,我能够将zip文件下载并保存到磁盘,提取其内容,然后从磁盘删除zip文件。很好但是,我想优化过程。 我找到了一种直接从下载的zip流中提取内容的方法,但是我必须指定文件名和扩展名。 我不确定在不指定它们的情况下如何在保留原始文件名和扩展名的同时提取内容。

当前方法:

string requestUri = "https://www.nuget.org/api/v2/package/" + PackageName + "/" + PackageVersion;
HttpResponseMessage response = await client.GetAsync(requestUri);
response.EnsureSuccessStatusCode();
using Stream PackageStream = await response.Content.ReadAsStreamAsync();
SaveStream($"{DownloadPath}.zip", PackageStream);
ZipFile.ExtractToDirectory($"{DownloadPath}.zip", ExtractPath);
File.Delete($"{DownloadPath}.zip");

// Directly extract Zip contents without saving file and without losing filename and extension
using (ZipArchive archive = new ZipArchive(await response.Content.ReadAsStreamAsync()))
{
   foreach (ZipArchiveEntry entry in archive.Entries)
   {
       using (Stream stream = entry.Open())
       {
           using (FileStream file = new FileStream("file.txt", FileMode.Create, FileAccess.Write))
           {
               stream.CopyTo(file);
           }
       }
   }
}

.NET 4.8
.NET Core 3.1
C#8.0

在这方面的任何帮助将不胜感激。
请随时评论其他方法或建议。
预先谢谢你。

1 个答案:

答案 0 :(得分:1)

ZipArchiveEntry具有NameFullName属性,可用于获取档案中文件的名称,同时保留其原始文件名和扩展名

FullName属性包含zip归档中条目的相对路径,包括子目录层次结构。 (相比之下,“名称”属性仅包含条目名称,不包括子目录层次结构。)

例如

using (ZipArchive archive = new ZipArchive(await response.Content.ReadAsStreamAsync())) {
    foreach (ZipArchiveEntry entry in archive.Entries) {
        using (Stream stream = entry.Open()) {                        
            string destination = Path.GetFullPath(Path.Combine(downloadPath, entry.FullName));

            var directory = Path.GetDirectoryName(destination);
            if (!Directory.Exists(directory))
                Directory.CreateDirectory(directory);

            using (FileStream file = new FileStream(destination, FileMode.Create, FileAccess.Write)) {
                await stream.CopyToAsync(file);
            }
        }
    }
}

将在与存储在归档文件中相同的子目录层次结构中提取文件,而如果使用entry.Name,则所有文件都将提取到相同位置。