I am trying to implement a "real time" progress bar that displays the progress of an async task (blob upload). The task is executed in a service (of a class library), which itself is called by a web controller.
Service method:
public async Task UploadFileToBlob(MemoryStream stream, string path, HttpContext context)
{
IProgress<StorageProgress> progressHandler = new Progress<StorageProgress>(
progress => context.Session.SetString("UploadBytesTransferred", progress.BytesTransferred.ToString());
CloudBlockBlob blob = GetBlockBlob();
await blob.UploadFromStreamAsync(stream, default(AccessCondition), requestOptions, default(OperationContext), progressHandler, new System.Threading.CancellationToken());
}
The controller call:
await _blobService.UploadFileToBlob(memoryStream, azureStoragePath, HttpContext);
The progress should later be retrieved by another controller action like here:
[HttpPost]
public ActionResult GetFileUploadProgress()
{
long progress = 0;
var sessionEntry = HttpContext.Session.GetString("UploadBytesTransferredPercent");
if (sessionEntry != null)
progress = Convert.ToInt64(sessionEntry);
return Json(progress);
}
My first try, as shown in the code, was to store the progress in a session variable, but it doesn't work and is probably not recommended. Is there a better and reliable way to get at the progress of the task? Or is something wrong with the code?
I ended up using MemoryCache to store the upload progress (it is not blocked by upload request). Probably not best practice, but sufficient for my needs.
public async Task UploadFileToBlob(MemoryStream stream, string path, IMemoryCache cache)
{
IProgress<StorageProgress> progressHandler = new Progress<StorageProgress>(
progress => cache.Set("UploadBytesTransferred", progress.BytesTransferred)
));
var blob = GetBlockBlob(path);
await blob.UploadFromStreamAsync(stream, default(AccessCondition), requestOptions, default(OperationContext), progressHandler, new System.Threading.CancellationToken());
}