У меня есть текстовое поле, в котором пользователь может отправить список идентификаторов документов, чтобы загрузить эти файлы, заархивированные из блоба 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)