Click here to Skip to main content
15,881,715 members
Articles / Programming Languages / Javascript

Upload Images To Azure Media Service From Client Side

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
4 Jul 2016CPOL5 min read 7.5K   2   4
How to upload images or any files to Media Service Account in Azure

In this article, we are going to see how we can upload images or any files to Media Service Account in Azure. If you are new to Azure media service account, I strongly recommend you read my previous post related to media service account. Once we create a media service account, we will create an asset and get the SAS token related to the asset we created, we will discuss more about asset and SAS token. I hope you will like this.

Background

For the past few weeks, I am working in Azure. Recently I got a requirement of storing images to Azure. Thus I decided to create a media service account for this requirement. The tricky part was I needed to upload the files from the client side itself. Here, we are going to see how we can create an Azure media service account and how to use the same.

What is Media Service Account?

  • A media service account is an Azure based account which gives you access to cloud based media services in Azure.
  • Stores metadata of the media files you create, instead saving the actual media content.
  • To work with media service account, you must have an associated storage account.
  • While creating a media service account, you can either select the storage account you already have or you can create a new one.
  • Since the media service account and storage account is treated separately, the content will be available in your storage account even if you delete your media service account

Please note that your storage account region must be the same as your media service account region.

Prerequisites

  • Visual Studio
  • Azure account with active subscription

If you are a start up company or you are thinking of starting one, you can always go for BizSpark (software and services made for the start ups), to join, please check here: How to join bizspark. Or you can always create a free account here.

Things We Are Going To Do

The following are the tasks we are going to do.

  • Creating an Azure media service account.

If you don’t have an Azure account with active subscription, you must create it first before going to do this task.

  • Create an Asset in Media service account
  • Get the SAS token for an Asset
  • Client side upload process
  • Retrieves the uploaded items

Now we will go and create our media service account.

Create an Azure Media Service Account

To create an Azure media service account, please see the link given below. I have explained the steps there.

Hope you have got the storage account and media service account with you.

Create an Asset in Media Service Account

You can always create an Asset either via code or manually in https://portal.azure.com.

Blob Service In Portal

Blob Service In Portal

New Container

New Container

If you want to create the Asset via code, you can create as below:

C#
public static string CreateBLOBContainer(string containerName)
        {
            try
            {
                string result = string.Empty;
                CloudMediaContext mediaContext;
                mediaContext = new CloudMediaContext(mediaServicesAccountName, mediaServicesAccountKey);
                IAsset asset = mediaContext.Assets.Create(containerName, AssetCreationOptions.None);
                return asset.Uri.ToString();
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

You can always get the sample code for creating the assets from here: Azure Media Service Account

Get the SAS Token for an Asset

Before going to generate SAS, we want to know what is a SAS right?

What is SAS?

SAS stands for shared access signature, it is the mechanism used for giving limited access to the objects in your storage account to your clients, in the way that you do not need to share your account key. In SAS, you can set how long the given access must be active and you can always set the read/write access too. If you want to know more about the SAS, I recommend you read here.

Once you downloaded the application from here, you can add a function to generate the SAS token dynamically.

C#
private static string GenerateSASToken(string assetId)
       {
           CloudStorageAccount backupStorageAccount = CloudStorageAccount.Parse(myAzureCon);
           CloudBlobClient client = backupStorageAccount.CreateCloudBlobClient();
           CloudBlobContainer container = client.GetContainerReference(assetId);
           BlobContainerPermissions permissions = container.GetPermissions();

           permissions.SharedAccessPolicies.Add(string.Concat
           (assetId, "AccessPolicy"), new SharedAccessBlobPolicy
           {
               Permissions = SharedAccessBlobPermissions.Read | SharedAccessBlobPermissions.Write,
               SharedAccessExpiryTime = DateTime.UtcNow.AddDays(365)
           });
           permissions.PublicAccess = BlobContainerPublicAccessType.Container;
           container.SetPermissions(permissions);

           ServiceProperties sp = client.GetServiceProperties();
           sp.DefaultServiceVersion = "2013-08-15";
           CorsRule cr = new CorsRule(); cr.AllowedHeaders.Add("*");
           cr.AllowedMethods = CorsHttpMethods.Get | CorsHttpMethods.Put | CorsHttpMethods.Post;
           cr.AllowedOrigins.Add("*");
           cr.ExposedHeaders.Add("x-ms-*");
           sp.Cors.CorsRules.Clear();
           sp.Cors.CorsRules.Add(cr);
           client.SetServiceProperties(sp);
           var sas = container.GetSharedAccessSignature
           (new SharedAccessBlobPolicy(), string.Concat(assetId, "AccessPolicy"));
           return container.Uri + sas;
       }

Here we are giving the asset id of the asset we just created. And the function will give you the SAS token we need. Hope you understood. Now we can start our client side coding for uploading.

Client Side Upload Process

Create an index page with an input file and other needed UI as follows:

HTML
<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="user-scalable=no, initial-scale=1, 
     maximum-scale=1, minimum-scale=1, width=device-width">
    <link href="CSS/Index.css" rel="stylesheet" />
</head>
<body>
    <div class="container">
        <div class="thumbnail-fit" id="azureImage">
            <div id="fiesInfo"></div>
            <div id="divOutput"></div>
        </div>
    </div>
    <div id="uploaderDiv">
        <form>
            <span class="input-control text">
                <input type="file" id="file" 
                multiple accept="image/*" name="file" />
            </span>
            <br />
            <br />
            <input type="button" 
            value="Upload File" id="buttonUploadFile" />
        </form>
    </div>
    <script src="scripts/jquery-1.10.2.min.js"></script>
    <script src="scripts/jquery-ui-1.9.2.min.js"></script>
    <script src="scripts/Index.js"></script>
</body>
</html>

Now create a JS file Index.js. And create a file change function as follows. Sounds good?

JavaScript
$(document).ready(function () {
    $('#fiesInfo').html('');
    $('#divOutput').html('');
    upldCount = 0;
    totSize = 0;

    $('#file').change(function () {
        selectedFile = [];
        if (this.files.length > 0) {
            $.each(this.files, function (i, v) {
                totalFileSize = totalFileSize + v.size;
                selectedFile.push({ size: v.size, name: v.name, file: v });
            });
        }
    });
});

Here we are pushing the selected files to an array in a needed format. Now we will add the upload click event.

JavaScript
$("#buttonUploadFile").click(function (e) {
    upload();
});

And following is the code for the function upload.

JavaScript
function upload() {
    $('#fiesInfo').html('');
    $('#divOutput').html('');
    upldCount = 0;
    totSize = 0;
    startDateTime = new Date();
    $('#fiesInfo').append('<span><b> 
    Uploading starts at </b></span>' + startDateTime);
    if (selectedFile == null) {
        alert("Please select a file first.");
    }
    else {
        for (var i = 0; i < selectedFile.length; i++) {
            fileUploader(selectedFile[i]);
            upldCount = upldCount + 1;;
            totSize = totSize + selectedFile[i].size;
        }
    }
};

Did you notice that we are calling a function inside a loop which accepts file content as parameter?

JavaScript
function fileUploader(selectedFileContent) {
    reader = new FileReader();
    var fileContent = selectedFileContent.file.slice(0, selectedFileContent.size - 1);
    reader.readAsArrayBuffer(fileContent);
    reader.onloadend = function (evt) {
        if (evt.target.readyState == FileReader.DONE) {
            var currentAzureStorageUrl = baseUrl;
            var indexOfQueryStart = currentAzureStorageUrl.indexOf("?");
            var uuid = generateUUID();
            var fileExtension = selectedFileContent.name.split('.').pop();
            var azureFileName = uuid + '.' + fileExtension;
            submitUri = currentAzureStorageUrl.substring(0, indexOfQueryStart) + 
                        '/' + azureFileName + currentAzureStorageUrl.substring(indexOfQueryStart);
            var requestData = new Uint8Array(evt.target.result);
            ajaxUploadCall(submitUri, requestData);
        }
    };
}

Here, baseUrl is the SAS you just created for an asset. The example of SAS is https://myaccount.blob.core.windows.net/sascontainer/sasblob.txt?sv=2015-04-05&st=2015-04-29T22%3A18%3A26Z&se=2015-04-30T02%3A23%3A26Z&sr=b&sp=rw&sip=168.1.5.60-168.1.5.70&spr=https&sig=Z%2FRHIX5Xcg0Mq2rqI3OlWTjEg2tYkboXr1P9ZUXDtkk%3D

Once the reader onloadend event is finished, we are passing the uri and data in the format of array. Can we see the AJAX call now?

JavaScript
function ajaxUploadCall(submitUri, selectedFileContent) {
    $.ajax({
        url: submitUri,
        type: "PUT",
        data: selectedFileContent,
        processData: false,
        async: false,
        beforeSend: function (xhr) {
            xhr.setRequestHeader('x-ms-blob-type', 'BlockBlob');
        },
        success: function (data, status) {

        },
        complete: function (event, xhr, settings) {
            compCount = compCount + 1;
            if (selectedFile.length == compCount) {
                RptDisplay();
            }
        },
        error: function (xhr, desc, err) {
        }
    });
}

In your Ajax call, please do not forget to add the header as below:

JavaScript
beforeSend: function (xhr) {
           xhr.setRequestHeader('x-ms-blob-type', 'BlockBlob');
       }

If every selected file is uploaded, we are calling a function RptDisplay() right?

JavaScript
function RptDisplay() {
    $('#divOutput').hide();
    $('#fiesInfo').append('<table></table>');
    $('#fiesInfo table').append('<tr><td><b>No of files uploaded: 
    </b></td><td>' + upldCount + '</td></tr>');
    $('#fiesInfo table').append('<tr><td><b>Total size uploaded: 
    </b></td><td>' + formatSizeUnits(totSize) + '</td></tr>');
    var endDateTime = new Date();
    $('#fiesInfo table').append('<tr><td><b>Uploading ends at 
    </b></td><td>' + endDateTime + '</td></tr>');
    $('#fiesInfo table').append('<tr><td><b>The time taken is 
    </b></td><td>' + findDateDiff(startDateTime, endDateTime) + 
    '</td></tr>');
    $('#divOutput').show();
};

You can get all the other needed functions like findDateDiff(), formatSizeUnits(), generateUUID() and the CSS from the source code attached. Please download the same. Now please run your page and you can find an input file there, select few files and try upload, if you have configured everything fine, I am sure you will get a report. Let us see that now.

Upload File

Upload File

Upload File Output

Upload File Output

Retrieves the Uploaded Items

To retrieve the items, you can always create a function as follows, which accepts asset id as parameter.

C#
public string getEventImage(string assetID)
        {
            CloudStorageAccount backupStorageAccount = CloudStorageAccount.Parse(myAzureCon);
            CloudBlobClient client = backupStorageAccount.CreateCloudBlobClient();
            CloudBlobContainer container = client.GetContainerReference
                                             (assetID.Replace("nb:cid:UUID:", "asset-"));
            List<string> results = new List<string>();
            foreach (IListBlobItem item in container.ListBlobs(null, false))
            {
                results.Add(item.Uri.ToString());
            }
            return JsonConvert.SerializeObject(results);
        }

Now if you login to your Azure portal and click on the asset you created, you can see the contents are uploaded there.

Uploaded Contents

Uploaded Contents

Conclusion

Did I miss anything that you may think is needed? Have you ever tried Azure media service account? Could you find this post useful? I hope you liked this article. Please share your valuable suggestions and feedback.

Your Turn. What Do You Think?

A blog isn’t a blog without comments, but do try to stay on topic. If you have a question unrelated to this post, you’re better off posting it on C# Corner, Code Project, Stack Overflow, ASP.NET Forum instead of commenting here. Tweet or email me a link to your question there and I’ll definitely try to help if I can.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Germany Germany
I am Sibeesh Venu, an engineer by profession and writer by passion. I’m neither an expert nor a guru. I have been awarded Microsoft MVP 3 times, C# Corner MVP 5 times, DZone MVB. I always love to learn new technologies, and I strongly believe that the one who stops learning is old.

My Blog: Sibeesh Passion
My Website: Sibeesh Venu

Comments and Discussions

 
GeneralThanks for sharing Pin
Mahsa Hassankashi7-Jul-16 6:08
Mahsa Hassankashi7-Jul-16 6:08 
GeneralRe: Thanks for sharing Pin
Sibeesh Passion7-Jul-16 6:33
professionalSibeesh Passion7-Jul-16 6:33 
GeneralMy vote of 5 Pin
Mahsa Hassankashi7-Jul-16 6:07
Mahsa Hassankashi7-Jul-16 6:07 
GeneralRe: My vote of 5 Pin
Sibeesh Passion7-Jul-16 6:33
professionalSibeesh Passion7-Jul-16 6:33 
Thank you so much dear Smile | :)
==================!!!====================!!!========================
So much complexity in software comes from trying to make one thing do two things.
Kindest Regards
Sibeesh Venu
http://sibeeshpassion.com/

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.