Вот с чем я имею дело ...
Некоторые процессы (вне нашего контроля) иногда помещают zip-файл в каталог в хранилище файлов Azure. Это имя каталога InBound
. Допустим, файл с именем bigbook.zip
помещен в папку InBound
.
Мне нужно создать приложение-функцию Azure, которое запускается каждые 5 минут и ищет zip-файлы в каталоге InBound
. Если что-то существует, то один за другим мы создаем новый каталог с тем же именем, что и zip-файл в другом каталоге (называемый InProcess
). Так что в нашем примере я бы создал InProcess/bigbook
.
Теперь внутри InProcess/bigbook
, мне нужно распаковать bigbook.zip
. Таким образом, к моменту завершения процесса InProcess/bigbook
будет содержать все содержимое bigbook.zip
.
Обратите внимание: эта функция, которую я создаю, является консольным приложением, которое будет работать как приложение-функция Azure. Таким образом, не будет доступа к файловой системе (по крайней мере, насколько мне известно, в любом случае.) Нет возможности скачать zip-файл, распаковать его, а затем переместить содержимое.
У меня дьявол времени, выясняющий, как сделать это только в памяти. Независимо от того, что я пытаюсь, я продолжаю сталкиваться с исключением Out Of Memory. Сейчас я просто делаю это на моем локальном хосте, работающем в режиме отладки в Visual Studio 2017, .NET 4.7. В этом случае я не могу преобразовать тестовый zip-файл размером 515 069 КБ.
Это была моя первая попытка:
private async Task<MemoryStream> GetMemoryStreamAsync(CloudFile inBoundfile)
{
MemoryStream memstream = new MemoryStream();
await inBoundfile.DownloadToStreamAsync(memstream).ConfigureAwait(false);
return memstream;
}
И это (с большими надеждами) была моя вторая попытка, думать, что DownloadRangeToStream
будет работать лучше, чем просто DownloadToStream
.
private MemoryStream GetMemoryStreamByRange(CloudFile inBoundfile)
{
MemoryStream outPutStream = new MemoryStream();
inBoundfile.FetchAttributes();
int bufferLength = 1 * 1024 * 1024;//1 MB chunk
long blobRemainingLength = inBoundfile.Properties.Length;
long offset = 0;
while (blobRemainingLength > 0)
{
long chunkLength = (long)Math.Min(bufferLength, blobRemainingLength);
using (var ms = new MemoryStream())
{
inBoundfile.DownloadRangeToStream(ms, offset, chunkLength);
lock (outPutStream)
{
outPutStream.Position = offset;
var bytes = ms.ToArray();
outPutStream.Write(bytes, 0, bytes.Length);
}
}
offset += chunkLength;
blobRemainingLength -= chunkLength;
}
return outPutStream;
}
Но в любом случае, у меня проблемы с памятью. Я полагаю, это потому, что MemoryStream, который я пытаюсь создать, становится слишком большим?
Как еще я могу заняться этим? И снова загрузка файла zip не является вариантом, поскольку в конечном итоге это будет приложение-функция Azure. Я также уверен, что использование FileStream также не вариант, так как для этого требуется локальный путь к файлу, которого у меня нет. (У меня есть только удаленный URL Azure)
Могу ли я как-нибудь создать временный файл в той же учетной записи хранилища Azure, в которой находится файл zip, и направить файл zip в этот временный файл, а не в поток памяти? (Мысли вслух.)
Цель состоит в том, чтобы получить поток в ZipArchive
, используя:
ZipArchive archive = new ZipArchive(stream)
И оттуда я могу извлечь все содержимое. Но достижение этой точки без ошибок памяти доказывает настоящий провал.
Есть идеи?