我目前有下面的代码,它使用 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。解决此异常的更好方法是什么?我想避免将任何文件写入磁盘。
所以这里的问题是
因此,您需要允许更大的物体(以某种方式)
<gcAllowVeryLargeObjects>
项目元素COMPlus_gcAllowVeryLargeObjects
但是,将 9 GB 的任何内容放在大型对象堆上是有问题的,除了其他问题之外,它对于 GC 来说效率很低,而且您确实应该尽可能避免 LOH。
注意取决于图书馆以及您可以访问的内容。可能有更少的LOHy方法可以做到这一点。如果您可以提供自己的流/数据结构,则有一些库可以分解缓冲区,这样它们就不会通过诸如
ReadOnlySequence
和 Microsoft 鲜为人知的 RecyclableMemoryStream
之类的东西在 LOH 上进行积极分配。
以下解决方案对我有用。不使用 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);
}
}
}