Исключение из нехватки памяти при сжатии потока памяти - PullRequest
0 голосов
/ 04 мая 2020

У меня есть текстовое поле, в котором пользователь может отправить список идентификаторов документов, чтобы загрузить эти файлы, заархивированные из блоба Azure.

Как код в настоящее время функционирует, создавая поток zip-памяти, а затем для каждый представленный идентификатор документа мы создаем поток памяти, получить файл из этого потока, а затем добавить его в ZIP-файл. Проблема в том, что мы создаем поток памяти и получаем файл, размер которого превышает 180 МБ, программа выдает исключение нехватки памяти.

Есть код

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);, она некоторое время будет сидеть и вращаться, а затем выбрасывать исключение нехватки памяти.

Я прочитал несколько разных решений, которые не работают для меня, наиболее распространенным является изменение целевого объекта Platform в свойствах по крайней мере на x64, и я запускаю его на x86. Другое решение, которое я мог бы увидеть, - переместить логи GetFileStream c в метод для BuildZipStream, но потом я чувствую, что метод будет делать слишком много.

Любые предложения?

РЕДАКТИРОВАТЬ: проблема на самом деле происходит, когда программа нажимает zip.Save(zipMemStream)

...