簡體   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