Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Download and display a private Azure Blob using ASP MVC

I'm using ASP MVC 5 Razor with Microsoft Azure Blob storage. I can successfully upload documents and images to the Blob Storage using MVC but I am struggling to find some MVC examples how to download and display the files.

It would be quite straightforward to do this if the blobs were stored as public files, but I need them to be private.

Can anyone give me any examples or guidance how to achieve this?

I've got some code below that seems to retrieve the Blob, but I'm not sure what to do with it in MVC to actually display it in a browser.

var fullFileName = "file1.pdf";
var containerName = "default";

// Retrieve storage account from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings["AttachmentStorageConnection"].ConnectionString);

// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

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

// Retrieve reference to a blob ie "picture.jpg".
CloudBlockBlob blockBlob = container.GetBlockBlobReference(fullFileName);
like image 258
Mitch Avatar asked Dec 02 '22 16:12

Mitch


2 Answers

I'm making an assumption based on your comment

It would be quite straightforward to do this if the blobs were stored as public files, but I need them to be private

that because the blobs are private you are attempting to return a byte array to the client via the mvc controller.

However, an alternate method would be to use a SharedAccessSignature to provide a client temporary access to the blob which you can then access as a public url. The period for which the url is valid can be specified in your controller. This also has the advantage of taking load away from your controller as the client will download the file directly from storage.

// view model
public class MyViewModel
{
    string FileUrl {get; set;}
}


// controller
public ActionResult MyControllerAction
{
    var readPolicy = new SharedAccessBlobPolicy()
    {
        Permissions = SharedAccessBlobPermissions.Read,
        SharedAccessExpiryTime = DateTime.UtcNow + TimeSpan.FromMinutes(5)
    };
    // Your code ------
    // Retrieve storage account from connection string.
    CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings   ["AttachmentStorageConnection"].ConnectionString);

    // Create the blob client.
    CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

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

    // Retrieve reference to a blob ie "picture.jpg".
    CloudBlockBlob blockBlob = container.GetBlockBlobReference(fullFileName);
    //------

    var newUri = new Uri(blockBlob.Uri.AbsoluteUri + blockBlob.GetSharedAccessSignature(readPolicy));

    var viewModel = new MyViewModel()
    {
        FileUrl = newUri.ToString()
    };

    return View("MyViewName", viewModel);
}

Then in your view you can use the view model value

//image
<img src="@Model.FileUrl" />
//in a new tab
<a href="@Model.FileUrl" target="_blank">`Open in new window`</a>
like image 59
Alex S Avatar answered Dec 27 '22 10:12

Alex S


I hope this answers your questions:

In order to download a file or open it in a new window/tab you need to specify the proper Content-Disposition in the header. There's an example here. Basically if you want to download a blob you execute the following. Keep in mind that if the mime type is set to application/octet-stream, the file will not be opened in a new tab. It will be downloaded. You need to set the correct ContentType when you save the blob in Azure.

//Downloads file
public ActionResult Index(string name)
{
    Response.AddHeader("Content-Disposition", "attachment; filename=" + name); 
    var blob = _azureBlobContainer.DownloadData(); //Code that returns CloudBlockBlob
    var memStream = new MemoryStream();
    blob.DownloadToStream(memStream);
    return File(memStream.ToArray(), blob.Properties.ContentType);
}

//Opens file if correct ContentType is passed
public ActionResult Index(string name)
{
    Response.AddHeader("Content-Disposition", "inline; filename=" + name); //Set it as inline instead of attached. 
    var blob = _azureBlobContainer.DownloadData(); //Code that returns CloudBlockBlob
    var memStream = new MemoryStream();
    blob.DownloadToStream(memStream);
    return File(memStream.ToArray(), blob.Properties.ContentType);
}

To open file in a new tab, make sure you specify the target in the view:

<a href="UrlToControllerAction" target="_blank"></a>

In regards to the blob being public/private, you should handle that in your interaction with Azure Storage. If you want to give users permission to access your blobs from outside your application, you should use a Shared Access Signature. Details here.

Hope this helps.

like image 33
lopezbertoni Avatar answered Dec 27 '22 11:12

lopezbertoni