如何跟踪异步文件上传到azure存储的进度

有没有办法跟踪文件上传进度到Azure存储容器?
我正在尝试使用C#创建一个用于将数据上传到azure的控制台应用程序。
我的coode现在看起来像:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.WindowsAzure.Storage; using Microsoft.WindowsAzure.Storage.Auth; using Microsoft.WindowsAzure.Storage.Blob; using System.Configuration; using System.IO; using System.Threading; namespace AdoAzure { class Program { static void Main(string[] args) { CloudStorageAccount storageAccount = CloudStorageAccount.Parse( ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString); CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient(); CloudBlobContainer container = blobClient.GetContainerReference("adokontajnerneki"); container.CreateIfNotExists(); CloudBlobClient myBlobClient = storageAccount.CreateCloudBlobClient(); CloudBlockBlob myBlob = container.GetBlockBlobReference("racuni.adt"); CancellationToken ca = new CancellationToken(); var ado = myBlob.UploadFromFileAsync(@"c:\bo\racuni.adt", FileMode.Open, ca); Console.WriteLine(ado.Status); //Does Not Help Much ado.ContinueWith(t => { Console.WriteLine("It is over"); //this is working OK }); Console.WriteLine(ado.Status); //Does Not Help Much Console.WriteLine("theEnd"); Console.ReadKey(); } } } 

这段代码运行良好,但我希望有一些进度条,所以用户可以看到有任务在做。 在WindowsAzure.Storage.Blob命名空间中是否有内置的东西,所以我可以用帽子作为兔子?

我不认为这是可能的,因为上传文件是一个单独的任务,即使内部文件被拆分成多个块并且这些块被上传,代码实际上等待整个任务完成。

一种可能性是手动将文件拆分为块并使用PutBlockAsync方法异步上传这些块。 上传PutBlockListAsync所有块后,您可以调用PutBlockListAsync方法提交blob。 请参阅下面的代码来完成:

 using Microsoft.WindowsAzure.Storage; using Microsoft.WindowsAzure.Storage.Auth; using Microsoft.WindowsAzure.Storage.Blob; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication1 { class Program { static CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials("accountname", "accountkey"), true); static void Main(string[] args) { CloudBlobClient myBlobClient = storageAccount.CreateCloudBlobClient(); myBlobClient.SingleBlobUploadThresholdInBytes = 1024 * 1024; CloudBlobContainer container = myBlobClient.GetContainerReference("adokontajnerneki"); //container.CreateIfNotExists(); CloudBlockBlob myBlob = container.GetBlockBlobReference("cfx.zip"); var blockSize = 256 * 1024; myBlob.StreamWriteSizeInBytes = blockSize; var fileName = @"D:\cfx.zip"; long bytesToUpload = (new FileInfo(fileName)).Length; long fileSize = bytesToUpload; if (bytesToUpload < blockSize) { CancellationToken ca = new CancellationToken(); var ado = myBlob.UploadFromFileAsync(fileName, FileMode.Open, ca); Console.WriteLine(ado.Status); //Does Not Help Much ado.ContinueWith(t => { Console.WriteLine("Status = " + t.Status); Console.WriteLine("It is over"); //this is working OK }); } else { List blockIds = new List(); int index = 1; long startPosition = 0; long bytesUploaded = 0; do { var bytesToRead = Math.Min(blockSize, bytesToUpload); var blobContents = new byte[bytesToRead]; using (FileStream fs = new FileStream(fileName, FileMode.Open)) { fs.Position = startPosition; fs.Read(blobContents, 0, (int)bytesToRead); } ManualResetEvent mre = new ManualResetEvent(false); var blockId = Convert.ToBase64String(Encoding.UTF8.GetBytes(index.ToString("d6"))); Console.WriteLine("Now uploading block # " + index.ToString("d6")); blockIds.Add(blockId); var ado = myBlob.PutBlockAsync(blockId, new MemoryStream(blobContents), null); ado.ContinueWith(t => { bytesUploaded += bytesToRead; bytesToUpload -= bytesToRead; startPosition += bytesToRead; index++; double percentComplete = (double)bytesUploaded / (double)fileSize; Console.WriteLine("Percent complete = " + percentComplete.ToString("P")); mre.Set(); }); mre.WaitOne(); } while (bytesToUpload > 0); Console.WriteLine("Now committing block list"); var pbl = myBlob.PutBlockListAsync(blockIds); pbl.ContinueWith(t => { Console.WriteLine("Blob uploaded completely."); }); } Console.ReadKey(); } } } 

Gaurav的解决方案效果很好,非常类似于http://blogs.msdn.com/b/kwill/archive/2011/05/30/asynchronous-parallel-block-blob-transfers-with-progress-change-notification.aspx 。 这段代码面临的挑战是你在很少的error handling方面做了很多复杂的工作。 我并不是说Gaurav的代码有任何问题 – 它看起来很稳定 – 但特别是对于网络相关的通信代码,你需要考虑很多变量和许多问题。

出于这个原因,我修改了原始博客以使用存储客户端库中的上传代码(假设来自Azure存储团队的代码比我能编写的任何内容更强大)并使用ProgressStream类跟踪进度。 您可以在http://blogs.msdn.com/b/kwill/archive/2013/03/06/asynchronous-parallel-block-blob-transfers-with-progress-change-notification-2-0查看更新的代码。 .aspx 。