Following the release of several new Azure features, I’ve been tinkering again with the various cloud offerings. I’m very impressed with this release, which brings ‘Virtual Machines’ for super-cheap, super-easy Virtual Private Server capability. In addition, the new ‘Websites’ model makes developing for Azure as easy as any other hosting provider – Git, FTP, TFS, and Web Publishing support make it super simple to get code up into the cloud, where you have buttery-smooth configuration and monitoring capabilities.
In the course of my tinkering, though, I whipped up a nifty little code snippet I thought I’d share. Say you’d like to let a user download a zip archive of files and folders stored in Azure Storage from an ASP.NET MVC or Web Forms app. Thanks to the de-facto standard .NET Zip library, SharpZipLib, this is relatively easy:
private void OutputBlobDirectoryAsZipDownload(CloudBlobDirectory directory) { byte[] buffer = new byte[4096]; Response.ContentType = "application/zip"; var fileName = directory.Uri.Segments.Last().Replace("/", ""); Response.AppendHeader("content-disposition", "attachment; filename=\"" + fileName + ".zip\""); Response.CacheControl = "Private"; Response.Cache.SetExpires(DateTime.Now.AddMinutes(3)); ZipOutputStream zipOutputStream = new ZipOutputStream(Response.OutputStream); zipOutputStream.SetLevel(3); //0-9, 9 being the highest level of compression var allFiles = directory.ListBlobs(new BlobRequestOptions { UseFlatBlobListing = true }).Where(x => x.GetType() == typeof(CloudBlockBlob)).Cast<CloudBlob>(); foreach (var file in allFiles) { Stream fs = file.OpenRead(); var entryName = file.Uri.ToString().Replace(directory.Uri.ToString(), ""); ZipEntry entry = new ZipEntry(ZipEntry.CleanName(entryName)); entry.Size = fs.Length; zipOutputStream.PutNextEntry(entry); int count = fs.Read(buffer, 0, buffer.Length); while (count > 0) { zipOutputStream.Write(buffer, 0, count); count = fs.Read(buffer, 0, buffer.Length); if (!Response.IsClientConnected) { break; } Response.Flush(); } fs.Close(); } zipOutputStream.Close(); Response.Flush(); Response.End(); }
This is essentially just their sample code adapted to work with Microsoft’s Azure StorageClient code. To use, simply use NuGet to add SharpZipLib and StorageClient to your app – it need not be an Azure application. Then call this code, passing in a CloudDirectory instance, and viola! Cloud files packaged in a single zip file for your users to download.
There are some caveats: there is an upper limit to the number of files the zip can contain, and likely in the size of the zip. I’m not sure this would work for downloading gigs of data. But, I can think of a few scenarios where it might be interesting.