繁体   English   中英

Out Of Memory 压缩时异常 memory stream

[英]Out Of Memory Exception when zipping memory stream

我有一个文本框,用户可以提交文档 ID 列表以下载从 Azure blob 压缩的那些文件。

代码当前如何运行构建一个 zip memory stream,然后对于提交的每个文档 ID,我们构建一个 memory stream,从该 stream 中获取文件,然后将其添加到 828.11109 文件中问题是我们正在构建 memory stream 并获取大于 180 mb 的文件程序抛出 out of memory 异常。

有代码

public async Task<byte[]> BuildZipStream(string valueDataUploadContainerName, IEnumerable<Document> docs)
        {

            var zipMemStream = new MemoryStream();

            using (Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile())
            {
                zip.Name = System.IO.Path.GetTempFileName();
                var insertedEntries = new List<string>();

                foreach (var doc in docs)
                {
                    var EntryName = $"{doc.Name}{Path.GetExtension(doc.DocumentPath)}";
                    if (insertedEntries.Contains(EntryName))
                    {
                        EntryName = $"{doc.Name} (1){Path.GetExtension(doc.DocumentPath)}";
                        var i = 1;
                        while (insertedEntries.Contains(EntryName))
                        {
                            EntryName = $"{doc.Name} ({i.ToString()}){Path.GetExtension(doc.DocumentPath)}";
                            i++;
                        }
                    }
                    insertedEntries.Add(EntryName);
                    var file = await GetFileStream(blobFolderName, doc.DocumentPath);
                    if (file != null)
                        zip.AddEntry($"{EntryName}", file);
                }

                zip.Save(zipMemStream);
            }

            zipMemStream.Seek(0, 0);
            return zipMemStream.ToArray();

然后实际从 blob 存储中获取文件

public async Task<byte[]> GetFileStream(string container, string filename)
        {

            var blobStorageAccount = _keyVaultService.GetSecret(new KeyVaultModel { Key = storageLocation });

            var storageAccount = CloudStorageAccount.Parse(blobStorageAccount ?? _config.Value.StorageConnection);
            var blobClient = storageAccount.CreateCloudBlobClient();
            var blobContainer = blobClient.GetContainerReference(container);

            await blobContainer.CreateIfNotExistsAsync();

            var blockBlob = blobContainer.GetBlockBlobReference(filename);
            if (blockBlob.Exists())
            {
                using (var mStream = new MemoryStream())
                {
                    await blockBlob.DownloadToStreamAsync(mStream);
                    mStream.Seek(0, 0);
                    return mStream.ToArray();
                }
            }
}

当程序点击await blockBlob.DownloadToStreamAsync(mStream); 它会坐下来旋转一会儿,然后抛出 memory 异常。

我已经阅读了一些对我不起作用的不同解决方案,最常见的是将属性下的平台目标更改为至少 x64,我在 x86 运行它。我能看到的另一个解决方案是移动 GetFileStream逻辑到 BuildZipStream 的方法中,但后来我觉得该方法会做太多。

有什么建议么?

编辑:当程序命中zip.Save(zipMemStream)时,问题实际上发生了

你这里的方法是有缺陷的。 因为你不知道:

  1. 文件数量。
  2. 每个文件的大小。

您无法准确确定服务器内存中的 memory 是否会实际容纳 memory 中的所有文件。您在这里所做的是收集他们列出的每个 Azure Blob 文件并将其放入 Zip 文件 IN MEMORY,同时下载每个文件都在 MEMORY 中。难怪你会遇到内存不足异常,即使有 128gb 的 RAM,如果用户请求足够大的文件,你也会用完 Memory。

下载和压缩多个 Azure Blob 文件的最佳解决方案和最常见的做法是使用临时 Blob 文件。

您不是写入 MemoryStream,而是写入 FileStream 并将该压缩文件放入 Azure Blob,然后提供该压缩 Blob 文件。 提供文件后,您将其从 Blob 中删除。

希望这可以帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM