Tuesday, 23 April 2013

Upload and Download Image in Windows Azure Blob Storage in MVC 3

I have been spent quite a bit time to find the solution in one of my projects, finally, I am able to crack it in the following way.
  1. Firstly create a separate controller class in the MVC project for managing the the operations with Images. I named it as AlbumController.
  2. This controller  class contains the action to handle the HttpPostedFile coming from View.
  3. I created a Model class for containing all the necessary methods for handling the operations with the Images.
I am going to describe in details for better understanding
public class AlbumController
    {
        private DiskFileStore fileStore = new DiskFileStore();

        public string AsyncUpload()
        {
            try
            {
                return fileStore.SaveUploadedFile(Request.Files[0]);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
     }
In the above code AsyncUpload is the action which is being used to handle the file submitted. I have created a custom model class named DiskFileStore looks like the following. I am using JQuery AsyncUpload plugin to upload my images in my project.

using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using System.Configuration;

internal class DiskFileStore
    {
         private string _downloadsFolder = HostingEnvironment.MapPath("~/Photos/");
        
         public string SaveUploadedFile(HttpPostedFileBase fileBase)
        {
            try
            {
                CloudStorageAccount csa = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["AzureStorageConnectionString"]);
                CloudBlobClient blobStorage = csa.CreateCloudBlobClient();

                var identifier = Guid.NewGuid();
                string identifierInLower = identifier.ToString().ToLower();

                string fileNameFromRequest = fileBase.FileName.ToLower();
                string fileExtension = fileNameFromRequest.Substring(fileNameFromRequest.IndexOf('.'));

                string originalFileName = identifierInLower + fileExtension;

                CloudBlobContainer cbcMain = blobStorage.GetContainerReference("photos");
                cbcMain.CreateIfNotExist();
                CloudBlob mainblob = cbcMain.GetBlobReference(originalFileName);
                mainblob.UploadFromStream(fileBase.InputStream);

                
                // Abhishek: Download the uploaded blob to local file to show the image at UI                
                CloudBlob savedBlob;
                savedBlob = blobStorage.GetBlobReference("photos/" + originalFileName);
                savedBlob.DownloadToFile(_downloadsFolder + originalFileName);

                return originalFileName;
            }
            catch (System.Runtime.InteropServices.ExternalException e)
            {
                throw e;
            }
            catch (Exception ex)
            {

                throw ex;
            }
            finally
            {

            }

        }
    }
In the above file I have done the following changes.

  1. I added Windows Azure references to my projects.
  2. I added a AzureConnectionString key to theWeb.Config file with the primary key values of my Azure Storage account.
  3. I created one folder named Photos under the root directory. ( As I need to to show back the uploaded image asynchronously in the view, hence I need to download the blob back to some local folder as image to take it as the source).
  4. Finally I am returning the image name which I am binding in a hidden field present in the view.(On submit of the form data I am saving the hidden field value as the image URL in the database).

2 comments:

  1. Title:Upload Images to Azure storage Account Inserted Information Store to Database using MVC

    Hi,

    TABLE: 

    ID Name ImageURL

    1 aaa http://example/Blob/Images/1.jpg

    At the time of inserting the data insert into sqlserver database along with Image Url like above example,The Image stored to Azure Storage account,

    At the time of Uploading image automatically store data in database above formate(Example I am giving)Images are store in Azure storage account using MVC

    In the same way Update,Delete,Display also

    Can you give me this example code or give me any sample example for this

    help me

    ReplyDelete
    Replies
    1. Hi Anil,

      As I was using asynchronous upload, the file would come as HttpPostedFileBase. From this you can get the file name like you mentioned 1.jpg.

      After the file got stored in the cloud storage as blob, you will be able to get the blob url something like the following.
      mainblob.UploadFromStream(fileBase.InputStream);
      string blobUri = mainblob.Uri.ToString();

      Now you can save this blobUri to your db using Entity Framework or LINQToSQL or ADO.NET with the file name as 1.jpg.

      But in the UI if you are maintaining a separate field for File Name, for that you have to use a button for postback the data along with uploaded image url for saving in the db.

      For displaying the data, you have to keep one thing in mind. As you are saving the blob url in the db, the blob container must to be public types. otherwise the image wont get accessible using the url. you need to use something like the following
      CloudBlobContainer cbcMain = blobStorage.GetContainerReference("Images");
      cbcMain.CreateIfNotExist();
      // Setting the container permission to public
      BlobContainerPermissions containerPermission = new BlobContainerPermissions();
      containerPermission.PublicAccess = BlobContainerPublicAccessType.Container;
      cbcMain.SetPermissions(containerPermission);

      Otherwise in case of more security with a private blob container, you can download the blob in byte[] and convert this to Base64 string.
      Then in the UI, you can set the image source to this base64 string with prefix "data:image/jpg;base64, ".

      byte[] downloadedImage = mainblob.DownloadByteArray();
      string baseString = "data:image/jpg;base64, " + Convert.ToBase64String(downloadedImage);

      Hope it will solve your problem.
      Thanks.

      Delete