Browser Direct Upload Data to Azure Blob Storage Part 1: CORS

Overview

I summarize three ways (e.g., Azure SDK) and the mechanism behind to enable Azure Blob Storage CORS in order to directly upload file data (e.g., image) from the  browser in this post.

Since Microsoft Azure Portal  has no entry to configure the CORS (Cross-origin resource sharing) for the Azure Storage service, one has to write actual code using the Azure SDK to achieve the desired configuration. I have kinda painful experience through trial and error figuring this out so I really need to write it down and hope to reduce the work for those who have similar purpose but little knowledge.

And I have to say I have little experience working with .NET framework which is why I think I got such a painful experience. So for those who are familiar with .NET or C#, they probably think it is easy to figure out how to do the job. However,  this post anyways could be an additional reference for them too hopefully. A brief introduction of Azure concepts would be given here too.

Microsoft Azure Basic Concepts

Well, Microsoft Azure is a similar platform to Amazon AWS. More concretely, Microsoft Azure is a cloud computing platform and infrastructure providing both PaaS and IaaS services, for building, deploying and managing applications and services through a global network of Microsoft-managed data centers. For example, it provides website hosting, data storage, .etc. And data storage is similar to Amazon S3 (You might also want to check these post series “HTML Direct Upload Data to Amazon S3 Part 0: Outline“) and it is also want we want to explore here.

There are three different type of Microsoft Azure Storage: Blob Storage, Table Storage, Queue Storage. We adopt the Blob Storage Service here mainly for unstructured data. Here is the official documentation introducing Blob storage and use the PHP SDK to do operations on it, this is the good start point from my experience: How to use the Blob service from PHP, Because I was searching around and saw different people say different things, I want to give direct, correct and informative reference here. So here is the goal: after reading that, you need to know basic concepts as indicated from the following figure:

Azure Blob Concepts

One important different between Azure Blob Storage from the Amazon S3 is that Azure Blob Storage does not support full path naming like sally/pics/personal/imag1.jpg. That is, there is only one layer Container, you cannot create any sub-layers under some specific container. While Amazon S3 does support create folder / sub-folders. Although they are all actually flat data, there is no real sub folder file systems in their low level implementations. But I think Amazon S3 is more user friendly even just making fake sub-folders structures for flat data because to users, it is a more convenient way to organize their data in a more clear structure.

I actually tested to create sub-container by specifying container name “pictures/personal” in the sample .NET code which we will examine soon, but it just reports error and there is no entry for us to create folder under the container menu. This is why I conclude that Azure Blob storage does not support sub-folder creation.

Three ways To Enable CORS for Blob Storage Service

In order to achieve directly upload client data from browser side into Azure Blob Storage without going through your actual application web server. You have to enable CORS on the Azure Blob side. I explain the mechanism behind about CORS and then I give straightforward approaches to enable CORS which actually requires writing a small amount of code.

CORS and Same-origin policy

The mechanism behind about this issue is that for security reasons, web browsers implement the same-origin policy security restriction that prevents a web page from calling an API in a different domain from the domain the page comes from. So if we want to direct access service provided by other provider (Azure Blob Storage service) from the page you get from our application web server (say www.ourown.com), you will get error telling you it is not allowed if Azure Blob Storage Service does not configure to accept such request from different domains.

Note this issue is caused purely because of browser security restriction. You can of course access the Azure Blob Storage Service from your own client say even a desktop application implemented using the Azure SDK, it is only when you try to access web services directly from the browser, you have to deal with this issue.  For instance, upload data from browser directly to Azure Blob Storage rather than upload it to your proxy server and then your server transfer the data to Azure Blob Storage, in later case, your proxy web server is acting as the client to access the blob service where it does not involve browser security issues of same-origin policy.

Here comes the role of Cross-Origin Resource Sharing (CORS) which allows us to configure a set of rules that define exceptions to the same-origin policy. That is, what if the web service allow such direct access? Obviously Azure Blob Storage could tell the browser, hey, it is OK, I trust this domain client, please let him or her access. Such human words are just translated by CORS. This post “Windows Azure Storage: Introducing CORS” gives good explanation about CORS as well as some other relevant concepts like preflight request, actual request and son on. Additionally, the post I just mentioned also gives example code which we can adopt to enable the CORS as well as complete .NET code to do direct uploading. If you just want use .NET to accomplish the task, this one is already enough for you to check, here what I want is just the code to enable CORS and I will do other parts using PHP instead.

The three approaches

Well, I have to say I really didn’t get used to .NET or C# stuff so I got  a painful experience even enabling CORS use the example code. And it turns out that PHP SDK does not have a direct API to enable CORS so I have to use  the Azure .NET SDK. I will give the three working approaches directly  and summarize the errors I have encountered with explanations for your information. You could enable CORS for Azure Blob Storage Service using the following three approaches:

(1) New a C# windows form application project say in your Visual Studio 2012. Manually add a reference to make sure you reference the  Microsoft.WindowsAzure.Storage.dll assembly. You can get these dll from internet. Then change the the code as follows:

using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using Microsoft.WindowsAzure.Storage.Shared.Protocol;
using Microsoft.WindowsAzure.Storage.Table;
using Microsoft.WindowsAzure;

        static void Main(string[] args)
        {
            String connectionString = "DefaultEndpointsProtocol=[http|https];AccountName=XXX;AccountKey=YYY";
            CloudStorageAccount AzureAccount = CloudStorageAccount.Parse(connectionString);
            CloudBlobClient BlobClient  = AzureAccount.CreateCloudBlobClient();
            ServiceProperties Properties = BlobClient.GetServiceProperties();
            CorsRule rules = new CorsRule();
            rules.AllowedMethods = CorsHttpMethods.Put | CorsHttpMethods.Options | CorsHttpMethods.Post | CorsHttpMethods.Delete | CorsHttpMethods.Get;
            rules.AllowedOrigins.Add("*");
            rules.AllowedHeaders.Add("*");
            rules.ExposedHeaders.Add("x-ms-*");
            rules.MaxAgeInSeconds = 300;
            Properties.Cors = new CorsProperties();
            Properties.Cors.CorsRules.Add(rules);
            BlobClient.SetServiceProperties(Properties);
        }

After changing the code into the above one, just click run so that the code could be executed to set the rules to Enable CORS for Azure Blob Service. For all the concepts like AccountName, AccountKey, you can refer to the official document for help. And note to customize the code by yourself, you need to replace XXX and YYY with your own and change the rules. For example, usually, the AllowedOrigins woundn’t be all (*), but a specific one of your proxy server.

Remarks: This is how even your native C# application could be able to access the Azure Blob Storage Service or other Azure Service, that is, you don’t have to create a azure cloud application in you VS 2012 and working on Web Role, Worker Roll things which a quite specific to Azure Stuff. My painful experience partially comes from struggling in figuring these web role, worker role things out and I thought the application has to be running on the Azure platform to configure the CORS. So the lesson I leaned from this is that when things become overwhelming, calm down first, and try to pinpoint the real requirement you want to meet and then find the correct solution to solve that.

(2) The second way would be directly using and executing the sample code from “Windows Azure Storage: Introducing CORS“. Download it, and do the folloing modification in AzureCommons.cs.

static String connectionString = "DefaultEndpointsProtocol=[http|https];AccountName=XXXX;AccountKey=YYY";
private static CloudStorageAccount StorageAccount = CloudStorageAccount.Parse(connectionString);
// The following is the original one in the sample code
// private static CloudStorageAccount StorageAccount = CloudStorageAccount.DevelopmentStorageAccount;

If you do not do the modification, you probably would encounter the following error when you build and execute the code.
Azure .NET Application ROOT Error

After the modification, just publish the project, so the code would be uploaded into Azure website. Visit the website and the CORS should be configured ready. Again, I have got headaches about this kind of error because of my less familiarity about Azure and .NET, I even try to modify web.config to remove such error and failed to solve it at first. For those who are expert on this, it shouldn’t be a problem.

(3) Download a free tool from “Cynapta Azure CORS Helper – Free Tool to Manage CORS Rules for Windows Azure Blob Storage“, since Azure portal does not have entry to configure CORS, someone just developed a simple desktop tool as a configuration Panel. You can specify you rules and enter your confidential data to change the CORS setting. But I suggest you regenerate your AccountKeys after using that for security concerns.

Summary

Three ways (e.g., Azure SDK) and the mechanism behind are given here to enable Azure Blob Storage CORS in order to directly upload file data (e.g., image) from the  browser. I also include some error shooting experience in this post which looks maybe quite naive after I got the whole thing working finally, but I just want to write it down and treat it as a lesson I leaned. Please feel free to leave any comments and share you ideas too. Thanks.


(Please specify the source  烟客旅人 sigmainfy — http://www.sigmainfy.com  as well as the original permalink

URL for any reprints,  and please do not use it for commercial purpose)

Written on October 16, 2014