Reputation: 461
I have some sort of an upload feature, which takes an image and resizes the image to different sizes, then returns a path of the 100x100 image to the user. In my case, the user is going to wait until all resizing and uploading is finished, which is obviously not good for the user experience. I Tried making my ActionResult as a Async Task, but im having trouble doing it. This is my code right now, which waits until all uploads are completed.
[HttpPost]
[Route("UploadProfileImage")]
public async Task<IHttpActionResult> UploadProfileImage()
{
string userId= Identifier.GetIdentifier();
ReturnResult response = new ReturnResult();
try
{
var provider = new MultipartMemoryStreamProvider();
await Request.Content.ReadAsMultipartAsync(provider);
var fileNameParam = provider.Contents[0].Headers.ContentDisposition.Parameters.FirstOrDefault(p => p.Name.ToLower() == "filename");
string fileName = (fileNameParam == null) ? "" : fileNameParam.Value.Trim('"');
byte[] file = await provider.Contents[0].ReadAsByteArrayAsync();
MemoryStream imgStream = new MemoryStream(file);
Bitmap mg = new Bitmap(imgStream);
List<Size> sizes = new List<Size>();
sizes.Add(new Size { Width = mg.Width, Height = mg.Height });
sizes.Add(new Size { Width = 100, Height = 100 });
sizes.Add(new Size { Width = 300, Height = 300 });
sizes.Add(new Size { Width = 500, Height = 500 });
sizes.Add(new Size { Width = 800, Height = 800 });
int index = 0;
foreach (var size in sizes)
{
byte[] newImageByteArray = Helpers.CreateImageThumbnail(file, Convert.ToInt32(size.Width), Convert.ToInt32(size.Height));
Helpers.SaveProfileImage(newImageByteArray, agentId, size, index == 0 ? true : false);
index++;
//---*--->>Here I Should check here that if original & 100x100 image were uploaded then return a response and continue uploading the others (if(index>1))
}
var path = "/users/uploads/100/" + userId+ ".jpg" + "?v=" + Guid.NewGuid();
UserManager.UpdateUploadImage(userId, path);
response.ReturnObject = path;
response.ReturnCode = ReturnCodes.Success;
return Ok(response);
}
catch (Exception ex)
{
response.ReturnObject = ex;
response.ReturnCode = ReturnCodes.Exception;
return Ok(response);
}
Note: the client is angularJS app that posts to the webapi server. Any idea how to rewrite the code in order to achieve this?
Upvotes: 0
Views: 297
Reputation: 456497
I Tried making my ActionResult as a Async Task, but im having trouble doing it.
That's not the correct solution, since async
doesn't change the HTTP protocol (as I describe on my blog). It can't be the correct solution because of this:
then returns a path of the 100x100 image to the user.
How would a web request return a response to the user, and then later return again (to return the path)? This isn't possible with a request/response protocol like HTTP; you only get one response per request.
In my case, the user is going to wait until all resizing and uploading is finished, which is obviously not good for the user experience.
Your options are:
Note that you're already doing (2):
the client is angularJS app that posts to the webapi server.
So, all you have to do is change the client so that it doesn't wait for the request before allowing the user to do other things. No server changes necessary.
Upvotes: 3