I'm still having trouble understanding how to use Async methods. I have the following code in a controller.
[HttpPost]
public async Task<IActionResult> ManualUpload([Bind("MktRpt")] ManualMktRptFileUpload itemFileUpload)
{
var manager = new RecyclableMemoryStreamManager();
using (var stream = manager.GetStream())
{
await itemFileUpload.MktRpt.CopyToAsync(stream);
await _azureStorageService.saveBlob(stream, Path.GetFileName(itemFileUpload.MktRpt.FileName));
}
itemFileUpload.status = "Success";
return View(itemFileUpload);
}
my service method is simple too:
public async Task saveBlob(MemoryStream stream, string filename)
{
var blockBlob = _container.GetBlockBlobReference(filename);
await blockBlob.UploadFromStreamAsync(stream);
}
along with a simple model class:
public class ManualMktRptFileUpload
{
[Required]
[Display(Name = "Manual Report")]
public IFormFile MktRpt { get; set; }
public string status { get; set; } = "Constructed";
}
When I check my Blob Container in Azure, the file is there BUT, it's zero bytes.
I believe this is because I am not correctly waiting for the stream to transfer, but I don't know how to fix it.
I doubt that this has anything to do with async really. Currently you're copying one stream into a MemoryStream
, but then leaving the "cursor" at the end of the MemoryStream
... anything trying to read from it won't see the new data.
The fix is really simple: just "rewind" the stream before you call your saveBlob
method:
using (var stream = manager.GetStream())
{
await itemFileUpload.MktRpt.CopyToAsync(stream);
stream.Position = 0;
await _azureStorageService.saveBlob(stream, Path.GetFileName(itemFileUpload.MktRpt.FileName));
}
Alternatively, avoid the copying into the MemoryStream
entirely:
using (var stream = itemFileUpload.MktRpt.OpenReadStream())
{
await _azureStorageService.saveBlob(stream, Path.GetFileName(itemFileUpload.MktRpt.FileName));
}
See more on this question at Stackoverflow