Upload to Azure Blob Storage with Shared Access Key

trailmax picture trailmax · Jun 23, 2013 · Viewed 13.2k times · Source

UPD: Here is my implemented solution to this problem

I'm trying to upload to Azure blob storage via Azure.Storage library (not REST API) and authenticating via Shared Access Key.

I have seen this blog post, but the API has changed since the post and now I can't get the same result.

Here is what I have:

var blobClient = new CloudBlobClient(new Uri(blobWithSas.BaseUri), new StorageCredentials(blobWithSas.Sas));


// here I receive 404 error
var blob = blobClient.GetBlobReferenceFromServer(new Uri(blobWithSas.AbsoluteUri));

using (var stream = new FileStream(fullFilePath, FileMode.Open))
{
    blob.UploadFromStream(stream);
}

Having:

blobWithSas.BaseUri = http://127.0.0.1:10000/devstoreaccount1/a6dc9274-6ce1-4095-be6b-e84d1012cb24 (Guid is name of the container, already exist, created somewhere else.)

blobWithSas.Sas = ?sv=2012-02-12&se=2013-06-23T03%3A04%3A53Z&sr=b&sp=w&sig=NaMqgXRMXDFvLAp8LTskgplAKp%2B9LCZzq8WK9Zo35x8%3D (also issued somewhere else in the code)

blobWithSas.AbsoluteUri = http://127.0.0.1:10000/devstoreaccount1/a6dc9274-6ce1-4095-be6b-e84d1012cb24/foldername/filename.txt

The blob does not exist, I want to upload new file and create a blob. I have "Server" application holding Access Key to Azure Storage Account. Server would issue SAS to clients and clients upload files directly to Azure. So SAS would be only to write, no reading and clients will be creating files where server tells them to (container, folder names)

The problem comes up on GetBlobReferenceFromServer - I get 404 error from Azure Storage. Yes, the blob does not exist and there is no reference. So given CloudBlobClient, how can I upload a file to a blob?

p.s. I realise there is REST API for these things. But I've used Microsoft.WindowsAzure.Storage library before and would like to avoid REST service if possible.

Answer

Stopped Contributing picture Stopped Contributing · Jun 23, 2013

The problem comes up on GetBlobReferenceFromServer - I get 404 error from Azure Storage. Yes, the blob does not exist and there is no reference. So given CloudBlobClient, how can I upload a file to a blob?

For GetBlobReferenceFromServer to work, the blob must be present in the blob storage. This is useful in the scenario when you know that the blob exist in storage and would want to find out the type of blob - Block Blob or Page Blob.

If you want to create a block blob by uploading a file from the local computer you could do something like:

    var blob = new CloudBlockBlob(new Uri(blobWithSas.AbsoluteUri), new StorageCredentials(blobWithSas.Sas));
using (var stream = new FileStream(fullFilePath, FileMode.Open))
{
    blob.UploadFromStream(stream);
}

Coming to shared access signature functionality, I wrote a blog post not too long ago about this: http://gauravmantri.com/2013/02/13/revisiting-windows-azure-shared-access-signature/. You can call it version 2 of Steve's blog post:). I've shown examples of uploading blobs with shared access signature using both REST API and Storage Client Library 2.0.

Some code samples from the blog post:

Using Storage Client Library:

/// <summary>
/// Uploads a blob in a blob container where SAS permission is defined on a blob container using storage client library.
/// </summary>
/// <param name="blobContainerSasUri"></param>
static void UploadBlobWithStorageClientLibrarySasPermissionOnBlobContainer(string blobContainerSasUri)
{
    CloudBlobContainer blobContainer = new CloudBlobContainer(new Uri(blobContainerSasUri));
    CloudBlockBlob blob = blobContainer.GetBlockBlobReference("sample.txt");
    string sampleContent = "This is sample text.";
    using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(sampleContent)))
    {
        blob.UploadFromStream(ms);
    }
}

Using REST API:

/// <summary>
/// Uploads a blob in a blob container where SAS permission is defined on a blob container using REST API.
/// </summary>
/// <param name="blobContainerSasUri"></param>
static void UploadBlobWithRestAPISasPermissionOnBlobContainer(string blobContainerSasUri)
{
    string blobName = "sample.txt";
    string sampleContent = "This is sample text.";
    int contentLength = Encoding.UTF8.GetByteCount(sampleContent);
    string queryString = (new Uri(blobContainerSasUri)).Query;
    string blobContainerUri = blobContainerSasUri.Split('?')[0];
    string requestUri = string.Format(CultureInfo.InvariantCulture, "{0}/{1}{2}", blobContainerUri, blobName, queryString);
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);
    request.Method = "PUT";
    request.Headers.Add("x-ms-blob-type", "BlockBlob");
    request.ContentLength = contentLength;
    using (Stream requestStream = request.GetRequestStream())
    {
        requestStream.Write(Encoding.UTF8.GetBytes(sampleContent), 0, contentLength);
    }
    using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
    {

    }
}

You may also find this blog post useful: http://gauravmantri.com/2013/02/16/uploading-large-files-in-windows-azure-blob-storage-using-shared-access-signature-html-and-javascript/