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
- 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.
- 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 = ""});
- Enable runAllManagedModulesForAllRequests in your web.config
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
...
</system.webServer>
The result
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.