Search code examples
c#streamzipazure-blob-storage

How to compress files to zip and upload to azure blob storage?


I'm having strange problem with this piece of code which basically zips files (docs) and uploads them to blob storage.

v11SDK: (docs)

var blockBlobClient = new BlockBlobClient(ConnectionString, ContainerName, "test-blob.zip");

// Saved zip is valid
// using (FileStream zipStream = new FileStream(@"C:\Users\artur\Desktop\test-local.zip", FileMode.OpenOrCreate))

// Uploaded zip is invalid
using (var stream = await blockBlobClient.OpenWriteAsync(true))
using (var archive  = new ZipArchive(stream, ZipArchiveMode.Create))
{
    var readmeEntry = archive .CreateEntry("Readme.txt");
    using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
    {
            writer.WriteLine("Information about this package.");
            writer.WriteLine("========================");
    }
    await stream.FlushAsync();
}

v12SDK: (docs)

var blobClient = new BlobClient(ConnectionString, InputContainerName, "test-blob.zip");

using var stream = new MemoryStream();
using (var archive = new ZipArchive(stream, ZipArchiveMode.Create))
{
    var readmeEntry = archive.CreateEntry("Readme.txt");
    using StreamWriter writer = new StreamWriter(readmeEntry.Open());
    {
        writer.WriteLine("Information about this package.");
        writer.WriteLine("========================");
        await writer.FlushAsync();
    }
    stream.Position = 0;
    await blobClient.UploadAsync(stream, true);
    await stream.FlushAsync();
}

Saving zip file locally produces a valid zip (164 bytes). Saving zip to blob storage (using storage emulator) produces invalid zip (102 bytes). I can't figure out why


Solution

  • Here is the correct code. The problem was premature disposing of inner stream by ZipArchive. Note in my code below, I have passed leaveInnerStreamOpen as true while creating ZipArchive since we are already disposing stream in the outer using. Also for V11 code, I have switched to MemoryStream instead of OpenWrite of blob stream since did not have control to set stream position to 0 if we use OpenWrite. And you don't need any Flush :)

    v11SDK:

            var blockBlobClient = new BlockBlobClient(ConnectionString, ContainerName, "test-blob.zip");
            using var stream = new MemoryStream();
            using (var archive = new ZipArchive(stream, ZipArchiveMode.Create, true))
            {
                var readmeEntry = archive.CreateEntry("Readme.txt");
                using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
                {
                    writer.WriteLine("Information about this package.");
                    writer.WriteLine("========================");
                }
            }
            stream.Position = 0;
            await blockBlobClient.UploadAsync(stream);
    

    v12SDK:

            var blobClient = new BlobClient(ConnectionString, InputContainerName, "test-blob.zip");
            using var stream = new MemoryStream();
            using (var archive = new ZipArchive(stream, ZipArchiveMode.Create, true))
            {
                var readmeEntry = archive.CreateEntry("Readme.txt");
                using StreamWriter writer = new StreamWriter(readmeEntry.Open());
                {
                    writer.WriteLine("Information about this package.");
                    writer.WriteLine("========================");
                }
            }
    
            stream.Position = 0;
            await blobClient.UploadAsync(stream, true);