CloudBlockBlob.DownloadToStream与DownloadRangeToStream

尝试使用ASP.NET azure SDK从blob存储中下载图像。

我在另一篇文章中读到,DownloadToStream确实将blob打破成小块并并行下载它们以提高性能。 我相信这就是DownloadRangeToStream的用途。

我无法找到任何关于DownloadToStream的文档或代码确认,并且持怀疑态度,因为它具有与blob url直接下载相同的运行时(每次下载.5-3s)。 这是我的下载方法的代码,给出了相同的性能。

使用CloudBlockBlob.DownloadToStream:

private Bitmap DownloadFromBlob(String set) { CloudStorageAccount storageAccount = CloudStorageAccount.Parse( CloudConfigurationManager.GetSetting("StorageConnectionString")); CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient(); CloudBlobContainer container = blobClient.GetContainerReference("templates"); CloudBlockBlob blockBlob = container.GetBlockBlobReference(set + ".png"); using (var memoryStream = new MemoryStream()) { blockBlob.DownloadToStream(memoryStream); return (memoryStream == null) ? null : (Bitmap)Image.FromStream(memoryStream); } } 

使用Image.FromStream:

 private Bitmap DownloadImageFromUrl(string url) { try { using (WebClient client = new WebClient()) { byte[] data = client.DownloadData(url); using (MemoryStream mem = (data == null) ? null : new MemoryStream(data)) { return (data == null || mem == null) ? null : (Bitmap)Image.FromStream(mem); } } } catch (WebException e) { return null; } } 

我试图增加图像的下载时间,范围从.5-12 MB。 我试图为这些图像实现我自己的DownloadRangeToStream方法,其代码如下。 我是否需要这样做或者DownloadToStream已经为我做了吗? 此方法产生与上面的DownloadFromBlob方法相同的运行时。

使用downloadRangeToStream:

 private Image getImageFromStream(string set) { CloudStorageAccount storageAccount = CloudStorageAccount.Parse( CloudConfigurationManager.GetSetting("StorageConnectionString")); CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient(); CloudBlobContainer container = blobClient.GetContainerReference("templates"); CloudBlockBlob blockBlob = container.GetBlockBlobReference(set + ".png"); using (MemoryStream ms = new MemoryStream()) { ParallelDownloadBlob(ms, blockBlob); return (ms == null) ? null : Image.FromStream(ms); } } private static void ParallelDownloadBlob(Stream outPutStream, CloudBlockBlob blob) { blob.FetchAttributes(); int bufferLength = 1 * 1024 * 1024;//1 MB chunk long blobRemainingLength = blob.Properties.Length; Queue<KeyValuePair> queues = new Queue<KeyValuePair>(); long offset = 0; while (blobRemainingLength > 0) { long chunkLength = (long)Math.Min(bufferLength, blobRemainingLength); queues.Enqueue(new KeyValuePair(offset, chunkLength)); offset += chunkLength; blobRemainingLength -= chunkLength; } Parallel.ForEach(queues, new ParallelOptions() { //Gets or sets the maximum number of concurrent tasks MaxDegreeOfParallelism = 10 }, (queue) => { using (var ms = new MemoryStream()) { blob.DownloadRangeToStream(ms, queue.Key, queue.Value); lock (outPutStream) { outPutStream.Position = queue.Key; var bytes = ms.ToArray(); outPutStream.Write(bytes, 0, bytes.Length); } } }); } 

根据我的理解, CloudBlockBlob.DownloadToStreamImage.FromStream都只会发送下载流的请求,您可以利用Fiddler捕获流量,如下所示:

使用DownloadRangeToStream ,您可以将blob分成更小的部分并自行并行下载以提高性能。 这是我的代码片段,你可以参考它。

 private static void ParallelDownloadBlob(Stream outPutStream, CloudBlockBlob blob) { blob.FetchAttributes(); int bufferLength = 1 * 1024 * 1024;//1 MB chunk long blobRemainingLength = blob.Properties.Length; Queue> queues = new Queue>(); long offset = 0; while (blobRemainingLength > 0) { long chunkLength = (long)Math.Min(bufferLength, blobRemainingLength); queues.Enqueue(new KeyValuePair(offset, chunkLength)); offset += chunkLength; blobRemainingLength -= chunkLength; } Parallel.ForEach(queues, new ParallelOptions() { //Gets or sets the maximum number of concurrent tasks MaxDegreeOfParallelism = 10 }, (queue) => { using (var ms = new MemoryStream()) { blob.DownloadRangeToStream(ms, queue.Key, queue.Value); lock (outPutStream) { outPutStream.Position = queue.Key; var bytes = ms.ToArray(); outPutStream.Write(bytes, 0, bytes.Length); } } }); } 

结果:

此外,还有一些关于上传/下载blob的博客,您可以参考它们( blog1和blog2 )。