1

I'm trying to figure out a way to upload a file through the web api without having to save the entire file to disk or memory along the way.

Here is my api controller code:

public async Task<IHttpActionResult>Post([FromUri] string ext) 
{
  string fileName = string.Concat(Guid.NewGuid(), ext);
  var blob = AzureBlobContainer.GetBlockBlobReference(fileName);
  await blob.UploadFromStream(await Request.Content.ReadAsStreamAsync()); // here is the issue
  return Ok();
}

I'm using HttpClient to do the upload:

public async Task<bool> Upload(string requestUrl, Stream fileStream)
{
  var progress = new ProgressMessageHandler();
  progress.HttpSendProgress += HttpSendProgress;
  var client = HttpClientFactory.Create(progress);
  HttpResponseMessage response = await client.PostAsync(requestUrl, new StreamContent(fileStream));
  response.EnsureSuccessStatusCode();
  return response.IsSuccessStatusCode;
}

private void HttpSendProgress(object sender, HttpProgressEventArgs e)
{
  Debug.WriteLine("progress is {0}% ({1} of {2})", e.ProgressPercentage, e.BytesTransferred, e.TotalBytes);
}

This code will successfully upload a file to Azure. However the entire file is being buffered on the web api server, and then copied to Azure. This causes the messages from the progress events to count up to 100% as the file is uploaded to the api controller, and then appears to block while the file is uploaded to Azure. I understand that because I am using StreamContent, web api shouldn't buffer my upload.

A solution is discussed in this question, which makes me think this is possible: WebAPI Request Streaming support

My client code is in a portable class library, so can't take any dependencies on the Azure .net storage library (so I can't directly upload to Azure, unless I use the underlying REST API)

Community
  • 1
  • 1
Zac
  • 283
  • 2
  • 7
  • Is it a Windows Phone 8/Windows 8 app? The reason I ask is because if that's the case, there might be some other alternatives. – Gaurav Mantri Jan 24 '14 at 07:31
  • The idea was to use a portable class library so it is designed to be used in either. – Zac Jan 24 '14 at 16:29

1 Answers1

1

As discussed in the linked you provided, you would need to set the buffer policy to be non-buffered mode at your service as by default the policy is to buffer.

StreamContent can hold either buffer or non-buffered streams and it does not decide whether the request stream at the host should be either buffered or not. Its the hosting layers which make this decision.

Kiran
  • 56,921
  • 15
  • 176
  • 161
  • Thanks I hadn't realized that it was only set to not buffer on StreamContent responses. Applying that does seem to improve the situation: now my progress event reflects the complete upload to Azure. However it still consumes a ton of memory in the worker process. e.g. if I upload a 100MB file memory usage increases to ~150MB by the time the file has been uploaded. It's as if the whole file is still being buffered on the server. – Zac Jan 24 '14 at 23:20