Part 4: How To Enable Clients To Access A File Share From An URL

While delving into Azure file service I came across a requirement to allow clients to access files from file storage using a URL. At the time of writing you cannot use Shared Access Signatures with file storage to grant them access. I am going to show one possible solution using ASP.NET MVC that will allow you to use a URL like this:

http://sitename.azurewebsites.net/Storage/RootFolder/Inroot.png
http://sitename.azurewebsites.net/Storage/RootFolder/SubFolder/File.png

Where the section of the URL in bold will match the exact path in your Azure file share and map to a file, in this case:

https://accountname.file.core.windows.net/ShareName/RootFolder/Inroot.png

In the example above Storage is just a friendlier name I chose as my route to the controller.

Steps

  1. In your MVC project create a new controller and add an action to it that will be used to retrieve the file:

    public class StorageController : Controller
    {
    public ActionResult StreamFile(string filepath)
    {
    string storagebase =        "https://StorageAccount.file.core.windows.net/ShareName/";
    var storageAccount = CloudStorageAccount.Parse(StorageConnectionString);
    var fileclient = storageAccount.CreateCloudFileClient();
    var fileUri = new Uri(storagebase + filepath, UriKind.Absolute);
    var azfile = new CloudFile(fileUri, fileclient.Credentials);
    return new FileStreamResult(azfile.OpenRead(), "image/png");
    }
    }

Note: I am streaming the file back, for scalability and performance reasons you do not want to read large files into memory.

  1. Add a new route. In this case I am redirecting all the requests for Storage to my StorageController and the StreamFile action, everything after the Storage section of the URL will be passed along in the filepath parameter

routes.MapRoute(
name: "Files",
url: "Storage/{*filepath}",
defaults: new {controller = "Storage", action = "StreamFile", filepath = ""});

  1. Enable runAllManagedModulesForAllRequests in your web.config

<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
...
</system.webServer>

The result

TestImage

We need runAllManagedModulesForAllRequests to enable ASP.NET to service the request instead of IIS. Keep in mind this is a demo and not meant for high performance sites. Enabling runAllManagedModulesForAllRequests is bad for performance since all managed modules will run for all requests.

Update: If you can’t or don’t want to change the code for your file access mechanism or you absolutely have to access the files using an SMB share you could move your application to an Azure Web Role which supports mounting a file share.

Francois Delport

Published by

Francois Delport

I am a cloud and devops consultant, technology fan and previously a professional C# developer with a keen interest in system design and architecture. Currently I am involved in projects using Azure, the Microsoft stack and DevOps. I am based in Melbourne, Australia. Email: [email protected]

Leave a Reply

Your email address will not be published. Required fields are marked *