Я пытаюсь загрузить ZIP-файл из контейнера BLOB-объектов Azure Storage и обработать его. В соответствии с требованиями моего варианта использования мне необходимо обрабатывать файл как поток памяти. Код следующий:
using System;
using System.IO.Compression;
using System.Text;
using Azure.Storage.Blobs;
class Program
{
async static Task Main(string[] args)
{
string blobContainerName = "test-container-001";
string blobName = "input/report.zip";
var containerClient = new BlobContainerClient("UseDevelopmentStorage=true", blobContainerName);
var blobClient = containerClient.GetBlobClient(blobName);
var content = await blobClient.DownloadContentAsync();
var file = content.Value.Content.ToString();
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(file)))
using (var zipArchive = new ZipArchive(stream, ZipArchiveMode.Read))
{
foreach(var e in zipArchive.Entries)
{
// Process files
Console.WriteLine(e.Name);
}
}
}
}
Когда программа перебирает записи Zip-архива, я получаю следующую ошибку:
System.IO.InvalidDataException: 'Number of entries expected in End Of Central Directory does not correspond to number of entries in Central Directory.'
Я могу прочитать Zip-файл со своего диска с помощью FileStream и без использования хранилища Azure или MemoryStream, но загрузка его из Azure с помощью этого метода вызывает эту ошибку. Может ли кто-нибудь дать совет по решению или диагностике этой проблемы?
InvalidDataException при чтении Zip-файла из большого двоичного объекта службы хранилища Azure.
Проблема, с которой вы столкнулись, связана с тем, как вы конвертируете blob content
в строку, а затем обратно в байтовый массивEncoding.UTF8.GetBytes(file)
, что приводит к повреждению данных ZIP-файла. Это связано с тем, что ZIP-файл представляет собой двоичные данные, и когда вы преобразуете его в строку и обратно в байты, двоичные данные изменяются, что приводит к повреждению ZIP-архива.
Вот код, который правильно загружает и обрабатывает ZIP-файл как поток памяти.
Код:
using System;
using System.IO;
using System.IO.Compression;
using Azure.Storage.Blobs;
class Program
{
async static Task Main(string[] args)
{
string blobContainerName = "test";
string blobName = "data.zip";
var containerClient = new BlobContainerClient("<your storage connection string>", blobContainerName);
var blobClient = containerClient.GetBlobClient(blobName);
var downloadResponse = await blobClient.DownloadStreamingAsync();
using (var memoryStream = new MemoryStream())
{
// Copy the blob content into the memory stream
await downloadResponse.Value.Content.CopyToAsync(memoryStream);
memoryStream.Position = 0;
using (var zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Read))
{
foreach (var entry in zipArchive.Entries)
{
Console.WriteLine(entry.Name);
}
}
}
}
}
Выход:
._sample-1.webp
._sample-1_1.webp
._sample-5.webp
._sample-5 (1).jpg
Ссылка: Загрузите большой двоичный объект с помощью .NET — Azure Storage | Microsoft Learn
Рад знать, что это помогло :)
Интересно, есть ли причина, по которой вам нужно копировать поток, возвращенный вызовом DownloadStreamingAsync()
, в новый поток memoryStream
?
Работает как надо, благодарю за помощь :)