Upload to Azure Blob Storage with Shared Access Key

14,093

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/

Share:
14,093
trailmax
Author by

trailmax

tech.trailmax.info - My blog. I write about C# and ASP.Net MVC (and sometimes about other random stuff) hrnet.trailmax.info My other blog. There I write about a technology I have been exposed for longer than I wanted. And now I know too much about HR.Net. This is part of my consulting service.

Updated on June 19, 2022

Comments

  • trailmax
    trailmax almost 2 years

    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.

  • trailmax
    trailmax almost 11 years
    Thank you! you are a star! I was missing creation of container object with SAS.
  • tster
    tster almost 10 years
    I found that the queryString was URL encoded, and the blobContainerSasUri was not, which made the Substring call not work properly. Replace that line with string blobContainerUri = blobContainerSasUri.Split('?')[0];