Controlar el progreso de una subida asíncrona de un blob a Azure Storage

El post de hoy viene porque no he sido capaz de encontrar un ejemplo de este escenario tan simple: estoy haciendo una subida de un archivo grande a un blob en Azure Storage en C# y me gustaría conocer el progreso, ya que va para largo 🙂 Aquí te dejo el código en un ejemplo de consola de cómo saber en qué punto de la subida está, haciendo uso de IProgress en la llamada:

using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using Microsoft.WindowsAzure.Storage.Core.Util;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace AzureBlobAsyncProgress
{
    class Program
    {
        static long totalBytes = 0;
        static void Main(string[] args)
        {

            UploadBlobAsync().GetAwaiter().GetResult();

            Console.WriteLine("Blob uploaded");
            Console.ReadLine();
        }

        static double ConvertBytesToMegabytes(long bytes)
        {
            return (bytes / 1024f) / 1024f;
        }

        private static async Task UploadBlobAsync()
        {
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse("YOUR_STORAGE_ACCOUNT_CONNECTION_STRING");

            var client = storageAccount.CreateCloudBlobClient();
            var container = client.GetContainerReference("wavs");
            await container.CreateIfNotExistsAsync();

            var file = File.Open("audio.wav", FileMode.Open);
            totalBytes = file.Length;
            var blob = container.GetBlockBlobReference(file.Name);

            var progressHandler = new Progress<StorageProgress>();
            progressHandler.ProgressChanged += ProgressHandler_ProgressChanged;

            //await blob.UploadFromStreamAsync(file);
            // UploadFromStreamAsync(Stream source, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext, IProgress<StorageProgress> progressHandler, CancellationToken cancellationToken);
            await blob.UploadFromStreamAsync(file, null, new BlobRequestOptions(), new OperationContext(), progressHandler, CancellationToken.None);

        }

        private static void ProgressHandler_ProgressChanged(object sender, StorageProgress e)
        {
            double dProgress = ((double)e.BytesTransferred / totalBytes) * 100.0;

            Console.WriteLine($"{dProgress.ToString("0.00")}% Bytes transferred: { ConvertBytesToMegabytes(e.BytesTransferred).ToString("0.00")}MB from {ConvertBytesToMegabytes(totalBytes).ToString("0.00")}MB");
        }
    }
}

Lo que estoy haciendo es utilizar una sobrecarga del método UploadFromStreamAsync en la que puedo utilizar un handler del tipo IProgress y así poder controlar el progreso de mi llamada asíncrona. El resultado sería parecido al siguiente:

Espero ahorrarte un ratito 🙂

¡Saludos!