Batched Media Upload to Azure Blob Storage through WebApi

Viewed 730

My web app currently allows users to upload media one-at-a-time using the following:

var fd = new FormData(document.forms[0]);
fd.append("media", blob); // blob is the image/video
$.ajax({
    type: "POST",
    url: '/api/media',
    data: fd
})

The media then gets posted to a WebApi controller:

    [HttpPost, Route("api/media")]
    public async Task<IHttpActionResult> UploadFile()
    {
        if (!Request.Content.IsMimeMultipartContent("form-data"))
        {
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
        }

        string mediaPath = await _mediaService.UploadFile(User.Identity.Name, Request.Content);

        return Ok(mediaPath);
    }

Which then does something along the lines of:

 public async Task<string> UploadFile(string username, HttpContent content)
 {
   var storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
   CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
   CloudBlobContainer imagesContainer = blobClient.GetContainerReference("container-" + user.UserId);
   var provider = new AzureStorageMultipartFormDataStreamProvider(imagesContainer);
   await content.ReadAsMultipartAsync(provider);
   var filename = provider.FileData.FirstOrDefault()?.LocalFileName;
   // etc
 }

This is working great for individual uploads, but how do I go about modifying this to support batched uploads of multiple files through a single streaming operation that returns an array of uploaded filenames? Documentation/examples on this seem sparse.

public class AzureStorageMultipartFormDataStreamProvider : MultipartFormDataStreamProvider
{
    private readonly CloudBlobContainer _blobContainer;
    private readonly string[] _supportedMimeTypes = { "images/png", "images/jpeg", "images/jpg", "image/png", "image/jpeg", "image/jpg", "video/webm" };

    public AzureStorageMultipartFormDataStreamProvider(CloudBlobContainer blobContainer) : base("azure")
    {
        _blobContainer = blobContainer;
    }

    public override Stream GetStream(HttpContent parent, HttpContentHeaders headers)
    {
        if (parent == null) throw new ArgumentNullException(nameof(parent));
        if (headers == null) throw new ArgumentNullException(nameof(headers));

        if (!_supportedMimeTypes.Contains(headers.ContentType.ToString().ToLower()))
        {
            throw new NotSupportedException("Only jpeg and png are supported");
        }

        // Generate a new filename for every new blob
        var fileName = Guid.NewGuid().ToString();

        CloudBlockBlob blob = _blobContainer.GetBlockBlobReference(fileName);

        if (headers.ContentType != null)
        {
            // Set appropriate content type for your uploaded file
            blob.Properties.ContentType = headers.ContentType.MediaType;
        }

        this.FileData.Add(new MultipartFileData(headers, blob.Name));

        return blob.OpenWrite();
    }
}
3 Answers
Related