Попытка использовать пакет SDK Azure ASP.NET для загрузки изображений из хранилища BLOB-объектов.
В другом посте я читал, что DownloadToStream разбивает большие двоичные объекты на более мелкие части и загружает их параллельно, чтобы повысить производительность. Я считаю, что это то, для чего нужен DownloadRangeToStream.
Мне не удалось найти какую-либо документацию или код, подтверждающий это утверждение о DownloadToStream, и я настроен скептически, потому что он имеет такое же время выполнения, как и просто загрузка прямо с URL-адреса большого двоичного объекта (0,5-3 с за загрузку). Вот код для обоих моих методов загрузки, дающий примерно одинаковую производительность.
Использование 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;
}
}
Я пытаюсь увеличить время загрузки изображений размером от 0,5 до 12 МБ. Я попытался реализовать свой собственный метод 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<long, long>> queues = new Queue<KeyValuePair<long, long>>();
long offset = 0;
while (blobRemainingLength > 0)
{
long chunkLength = (long)Math.Min(bufferLength, blobRemainingLength);
queues.Enqueue(new KeyValuePair<long, long>(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);
}
}
});
}