title: Batched Media Upload to Azure Blob Storage through WebApi
body: <p>My web app currently allows users to upload media one-at-a-time using the following:</p>
  
  <pre><code>var fd = new FormData(document.forms[0]);
  fd.append("media", blob); // blob is the image/video
  $.ajax({
      type: "POST",
      url: '/api/media',
      data: fd
  })
  </code></pre>
  
  <p>The media then gets posted to a WebApi controller: </p>
  
  <pre><code>    [HttpPost, Route("api/media")]
      public async Task&lt;IHttpActionResult&gt; 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);
      }
  </code></pre>
  
  <p>Which then does something along the lines of:</p>
  
  <pre><code> public async Task&lt;string&gt; 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
   }
  </code></pre>
  
  <p>This is working great for individual uploads, but how do I go about modifying this to support batched uploads of <em>multiple</em> files through a single streaming operation that returns an array of uploaded filenames?  Documentation/examples on this seem sparse. </p>
  
  <pre><code>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();
      }
  }
  </code></pre>