Using Windows Azure Blob Storage to store aerial images


The scenario

I have an ASP.NET web application, which is used to search and navigate over a very large number of aerial images. Currently there are nearly 400.000 images consuming 2 TB of storage + backups.

image

I thought it would be a good idea to see how the Windows Azure Blob storage could be used to store the aerial photos for my application. I wanted to do this without moving the entire web application to Windows Azure (taking one step at a time). Since Windows Azure currently is in beta, I only have about 50GB of cloud storage to play with. Therefore, I will start by moving all the lower resolution images to the Windows Azure Blob Storage.

Create a new Storage Project in Windows Azure

Before we can start to upload the images to the Windows Azure Blob Storage, we need to create a new Storage Account in the Azure Services Developer Portal:

image

When you go through the process for creating a new Storage Account, you will get the required Endpoints and Access Keys for working with the Blob Storage from your code.

Uploading the Images to Windows Azure Blob Storage

To upload the images from my local storage to the Windows Azure Blob Storage in the Microsoft cloud datacenter, I decided to write a small and simple console program. This would iterate through all the image files in a given directory and upload each image. From my datacenter in Norway, this process would typically upload between 4000 and 6000 images per hour for small 50 kB thumbnail images.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Samples.ServiceHosting.StorageClient;
using System.Collections.Specialized;
using Microsoft.ServiceHosting.ServiceRuntime;
using System.IO;
using MapaidLibrary.BusinessLogic;
using MapaidLibrary.Entities;

namespace UploadPhotos
{
    class Program
    {
        static string sourceDirectory = @"\\leopard\mapaid\photos\l1";
        static string targetContainer = "photosl1";

        static BlobContainer _Container = null;

        static void Main(string[] args)
        {
            // Get the configuration from the cscfg file
            StorageAccountInfo accountInfo = StorageAccountInfo.GetDefaultBlobStorageAccountFromConfiguration();

            // Container names have the same restrictions as DNS names
            BlobStorage blobStorage = BlobStorage.Create(accountInfo);
            _Container = blobStorage.GetBlobContainer("photosl1");

            // Make the container public so that we can hit the URLs from the web
            _Container.CreateContainer(new NameValueCollection(), ContainerAccessControl.Public);

            var files = from file in Directory.GetFiles(sourceDirectory) select file;

            int i = 0;

            DateTime startTime = DateTime.Now;
            foreach (string file in files)
            {
                UploadPhoto(file);
                i++;
            }

        }

        static void UploadPhoto(string fromPath)
        {
            try
            {
                FileStream fs = File.OpenRead(fromPath);

                byte[] data = new byte[fs.Length];
                fs.Read(data, 0, data.Length);
                fs.Close();

                string blobFilename = Path.GetFileName(fromPath);
                BlobProperties properties = new BlobProperties(blobFilename);

                // Create metadata to be associated with the blob
                NameValueCollection metadata = new NameValueCollection();
                metadata["FileName"] = blobFilename;

                properties.Metadata = metadata;
                properties.ContentType = "image/jpeg";

                //// Create the blob
                BlobContents fileBlob = new BlobContents(data);
                bool ok = _Container.CreateBlob(properties, fileBlob, true);
            }
            catch (FileNotFoundException ex)
            {
                Console.WriteLine("File not found: " + fromPath);
            }

        }
    }
}

This needs to be added to the App.config file:

<appSettings>
    <add key="AccountName" value="YourAccount"/>
    <add key="AccountSharedKey" value="YourSharedKey/"/>
    <add key="BlobStorageEndpoint" value="http://blob.core.windows.net"/>
</appSettings>

Using the images from the Windows Azure Blob Storage

After uploading all the images, I would now be able to access the images by a simple URL like this:

http://youraccount.blob.core.windows.net/photosl1/50389339.jpg

In my ASP.NET web application, I simply had to change the URL of an ASP.NET Image tag like this:

<asp:Image runat="server" Width="193" Height="128" ImageUrl='<%# Eval("PhotoId", "http://youraccount.blob.core.windows.net/photosl1/{0}.jpg") %>’

Now my aerial images are served directly from a Windows Azure datacenter!

I have been using the Windows Azure Blob Storage for a few months now (since the PCD 2008) and even if the service is in beta, I have not experienced any issues accessing the images from my web application.


Comments (4)

  1. I found this cool post on how to use azure blob storage to store your images. This post includes some

  2. yamillemorales says:

    Hi there,

    Quick question. Would you know how I could upload a thumbmail of an image instead of the image per se. I’m using the FileUpload control in asp.net (c#) but can’t get around to upload this. Also tried resizing the image before uploading to the BLOB, but I’m stuck at the point where I have to feed the straem of the modified picture or thumbnail.

    Any help is appreciated,

    YM

  3. Magick says:

    Hi

    Does this code refer to an old version of the Azure SDK?

    The reason I ask is I'm having some trouble with the code. I cannot find a BlobContents class. And the BlobProperties class does not have a Metadata property.

    Do you know what the newer equivalent of these would be?

    Thanks

  4. Archi says:

    I have tried to convert a video file to multiple images using FFMPEG. Do you have any idea how to upload these images to the blob ???