从 azure blob 下载大型 zip 文件并解压缩

问题描述 投票:0回答:2

我目前有下面的代码,它使用 SAS URI 从 blob 下载 zip 文件,解压缩并将内容上传到新容器

        var response = await new BlobClient(new Uri(sasUri)).DownloadAsync();
        using (ZipArchive archive = new ZipArchive(response.Value.Content))
        {
            foreach (ZipArchiveEntry entry in archive.Entries)
            {
                BlobClient blobClient = _blobServiceClient.GetBlobContainerClient(containerName).GetBlobClient(entry.FullName);
                using (var fileStream = entry.Open())
                {
                    await blobClient.UploadAsync(fileStream, true);
                }
            }
        }

我的代码因“流太长”异常而失败: System.IO.IOException:流太长。在System.IO.MemoryStream.Write(Byte []缓冲区,Int32偏移量,Int32计数)在System.IO.Stream.CopyTo(流目的地,Int32 bufferSize)在System.IO.Compression.ZipArchive.Init(流流,ZipArchiveMode)模式,布尔型 leftOpen).

我的zip文件大小是9G。解决此异常的更好方法是什么?我想避免将任何文件写入磁盘。

c# .net .net-core azure-blob-storage c#-ziparchive
2个回答
1
投票

所以这里的问题是

  1. .Net 的数组大小是有限的(取决于平台)。
  2. 数组返回作为缓冲区或内存数据存储。
  3. 在 64 位平台上,数组大小为 2 GB
  4. 您想要将 9 gig 流(由数组支持)放在大型对象堆上。

因此,您需要允许更大的物体(以某种方式)

允许大型物体

  • 在 .Net Framework 4.5+ 中,您可以设置
    <gcAllowVeryLargeObjects>
    项目元素
  • 在核心中,您需要设置环境变量
    COMPlus_gcAllowVeryLargeObjects

但是,将 9 GB 的任何内容放在大型对象堆上是有问题的,除了其他问题之外,它对于 GC 来说效率很低,而且您确实应该尽可能避免 LOH。

注意取决于图书馆以及您可以访问的内容。可能有更少的LOHy方法可以做到这一点。如果您可以提供自己的流/数据结构,则有一些库可以分解缓冲区,这样它们就不会通过诸如

ReadOnlySequence
和 Microsoft 鲜为人知的
RecyclableMemoryStream
之类的东西在 LOH 上进行积极分配。


1
投票

以下解决方案对我有用。不使用 DownloadAsync,而是使用 OpenReadAsync

var response = await new BlobClient(new Uri(sasUri)).OpenReadAsync(new BlobOpenReadOptions(false), cancellationToken);
using (ZipArchive archive = new ZipArchive(response))
{
    foreach (ZipArchiveEntry entry in archive.Entries)
    {
        BlobClient blobClient = _blobServiceClient.GetBlobContainerClient(containerName).GetBlobClient($"{buildVersion}/{entry.FullName}");
        using (var fileStream = entry.Open())
        {
           await blobClient.UploadAsync(fileStream, true, cancellationToken).ConfigureAwait(false);
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.