8
votes

We're using ASP.NET MVC 4 to allow users to upload video and audio through our website. I would like to use Azure Media Service as the back-end for this.

While following Azure's tutorial, the issue I've run into is that the Azure Media Services SDK doesn't appear to allow uploading a raw stream of data. Instead, the only upload method I could find uses a path string argument.

I would like to avoid saving the file to disk (it's already streamed to disk by default), and be able to stream the request posted file right through to Azure.

Here is my code thus far:

public void SaveMedia(string fileName, System.IO.Stream stream)
{
    CloudMediaContext mediaCloud = new CloudMediaContext("account", "key");
    AssetCreationOptions assetOptions = new AssetCreationOptions();
    var asset = mediaCloud.Assets.Create(fileName, assetOptions);

    var assetFile = asset.AssetFiles.Create(fileName);

    var accessPolicy = mediaCloud.AccessPolicies.Create(fileName, TimeSpan.FromDays(3), AccessPermissions.Write | AccessPermissions.List);

    var locator = mediaCloud.Locators.CreateLocator(LocatorType.Sas, asset, accessPolicy);

    assetFile.Upload("????????????");

    locator.Delete();
    accessPolicy.Delete();
}

How does one accomplish this? Would this conflict with any "best practices" for handling uploads using ASP.NET MVC 4 and Azure Media Services?

1

1 Answers

11
votes

You should use not use the Azure Media Services to do the upload, it is not designed for inbound-stream-to-azure-storage-blob, which is what you are describing.

Use the Azure Storage SDK directly (use v1.7 to avoid rebinding issues). The Storage SDK allows stream writes to blob. To do this, you need to first get a SAS write locator (looks like you're there), then use the locator.Path.Segments to find the asset container. Then use this to upload directly using CloubBlobClient in the Storage SDK -- it offers a stream write function somewhere.

Note in your code above: you are not specifying AssetCreationOptions.None, therefor it will assume that the files in storage will be storage-encrypted (default transfer mechanism is secure, not unsecured). I don't think you are going to do the storage encryption on your file-stream prior to upload, so you'd best set that to AssetCreationOptions.None.

Personally, I would not go this route. Read my blog post on 'create your own youtube': http://blog-ndrouin.azurewebsites.net/?p=1471

In it, there is a full example of client-uploaded content using a SAS url provided by the server side (which has your account credentials, that you probably don't want floating around on your client-side!).

The client, however, must be able to do a PUT into storage using that SAS URL. In my case, I used a C# command line app. You will not be able to do this in HTML5 unless your web-page is hosted on the same domain as the target storage account. If your web-page (or an I-Frame that manages the uploads) is not in the same domain as your storage account, this will trigger a CORS "OPTIONS" call in HTML5 to the Azure Storage REST layer, which not yet support CORS.

Alternatives to an HTML5 I-Frame hosted in your storage account are: Sliverlight or Flash upload shims with a cross-domain file in the $root of your storage account (or perhaps those plugin objects hosted in your storage account to avoid the cross-domain-file request).

I would discourage uploading the filestream to the server in a POST. This makes your web-service a bottleneck for all inbound files; and a long POST is not particularly stable: your app-pool can get recycled in the middle of an upload and you're toast.

PS. Our team (Windows Azure Media Services) primarily monitors this forum:

http://social.msdn.microsoft.com/Forums/en-US/MediaServices/threads