JQuery Mobile
JQuery Mobile

Reputation: 6291

Upload Picture to Windows Azure Web Site

I have an ASP.NET MVC 4 app that i want to deploy to Windows Azure. A part of this app involves uploading a picture. When the picture is uploaded, I want to store the picture in a directory located at /pictures/uploaded.

My question is, how do I upload a picture to a relative path within my app hosted on Windows Azure? Up to this point, my app has been hosted in a Virtual Machine. I was able to do the above by using the following:

string path = ConfigurationManager.AppSettings["rootWebDirectory"] + "/pictures/uploaded;

// Get the file path
if (Directory.Exists(path) == false)
  Directory.CreateDirectory(path);

string filePath = path + "/uploaded" + DateTime.UtcNow.Milliseconds + ".png";
filePath = filePath.Replace("/", "\\").Replace("\\\\", "\\");

// Write the picture to the file system
byte[] bytes = GetPictureBytes();
using (FileStream fileStream = new FileStream(filePath, FileMode.Create))
{
  fileStream.Write(bytes, 0, bytes.Length);
  fileStream.Flush();
  fileStream.Close();
}

Currently, ConfigurationManager.AppSettings["rootWebDirectory"] points to an absolute path. I belive this is where my problem lies. I can't figure out how to switch all of this to a relative path.

Thank you!

Upvotes: 13

Views: 19403

Answers (4)

Magnus Karlsson
Magnus Karlsson

Reputation: 3579

Here is my as easy as it comes description of how to set this up in azure. http://geekswithblogs.net/MagnusKarlsson/archive/2012/12/02/how-to-use-azure-storage-for-images.aspx

//Edit; heres the complete example from my blog(if the blog dies). yourViewName.cshtml

 @model List<string>  
 @{
     ViewBag.Title = "Index";
 }

 <h2>Index</h2>
 <form action="@Url.Action("Upload")" method="post" enctype="multipart/form-data">

     <label for="file">Filename:</label>
     <input type="file" name="file" id="file1" />
     <br />
     <label for="file">Filename:</label>
     <input type="file" name="file" id="file2" />
     <br />
     <label for="file">Filename:</label>
     <input type="file" name="file" id="file3" />
     <br />
     <label for="file">Filename:</label>
     <input type="file" name="file" id="file4" />
     <br />
     <input type="submit" value="Submit" />

 </form>

 @foreach (var item in Model) {

     <img src="@item" alt="Alternate text"/>
  }

Your controller action

public ActionResult Upload(IEnumerable<HttpPostedFileBase> file)
         {
             BlobHandler bh = new BlobHandler("containername");
             bh.Upload(file);
             var blobUris=bh.GetBlobs();

             return RedirectToAction("Index",blobUris);
         }

Your model

 public class BlobHandler
     {
         // Retrieve storage account from connection string.
         CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
         CloudConfigurationManager.GetSetting("StorageConnectionString"));

         private string imageDirecoryUrl; 

         /// <summary>
         /// Receives the users Id for where the pictures are and creates 
         /// a blob storage with that name if it does not exist.
         /// </summary>
         /// <param name="imageDirecoryUrl"></param>
         public BlobHandler(string imageDirecoryUrl)
         {
             this.imageDirecoryUrl = imageDirecoryUrl;
             // Create the blob client.
             CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

             // Retrieve a reference to a container. 
             CloudBlobContainer container = blobClient.GetContainerReference(imageDirecoryUrl);

             // Create the container if it doesn't already exist.
             container.CreateIfNotExists();

             //Make available to everyone
             container.SetPermissions(
                 new BlobContainerPermissions
                 {
                     PublicAccess = BlobContainerPublicAccessType.Blob
                 });
         }

         public void Upload(IEnumerable<HttpPostedFileBase> file)
         {
             // Create the blob client.
             CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

             // Retrieve a reference to a container. 
             CloudBlobContainer container = blobClient.GetContainerReference(imageDirecoryUrl);

             if (file != null)
             {
                 foreach (var f in file)
                 {
                     if (f != null)
                     {
                         CloudBlockBlob blockBlob = container.GetBlockBlobReference(f.FileName);
                         blockBlob.UploadFromStream(f.InputStream);
                     }
                 }
             }
         }

         public List<string> GetBlobs()
         {
             // Create the blob client. 
             CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

             // Retrieve reference to a previously created container.
             CloudBlobContainer container = blobClient.GetContainerReference(imageDirecoryUrl);

             List<string> blobs = new List<string>();

             // Loop over blobs within the container and output the URI to each of them
             foreach (var blobItem in container.ListBlobs())
                 blobs.Add(blobItem.Uri.ToString());

             return blobs;
         }
     }

Upvotes: 21

marvc1
marvc1

Reputation: 3689

Data and images are not meant to be stored in website directory. That's why there is the Azure Blob Storage.

Azure works by copying the website out to an instance, so if more than one instance exists then uploaded images (which are stored local to the instance) will become out of sync, you will even loose images if there are conflicts.

If you really want to do it the line below will give you what you want:

string path = Server.MapPath("~/pictures/uploaded");

Upvotes: 10

Robert Greiner
Robert Greiner

Reputation: 29722

There are some good answers here already that tell you exactly how to do what you need. Allow me to propose an alternative if you don't mind.

Personally, to solve problems such as yours, I turn to Azure Blob Storage. Blob storage is an extremely cheap and fast method of storing binary files (in a folder type structure) completely separate from the VM your cloud service is currently running on.

This will allow you some additional freedom when migrating or developing against your existing application since you don't have to migrate your uploads along with each deployment. Blob storage files are also triple-replicated across multiple Azure datacenters at no additional cost to you and are much more fault tolerant than your deployment VM.

Moving to Blob Storage will also allow you to access your files when your site is offline or your VM is down.

You are no longer operating in the realm of shared computing where all resources must exist on the same machine. Azure was built for scalability and separation of resources. Blob storage was designed specifically for what you are trying to do here.

Upvotes: 3

ctrlalt313373
ctrlalt313373

Reputation: 4065

string path = HostingEnvironment.MapPath(@"~/pictures/uploaded");

Upvotes: -1

Related Questions