2012-06-05 1 views
12

Я пытаюсь загрузить файл из cloudBlob через поток. Я имею в виду эту статью CloudBlobCloudBlob.DownloadToStream возвращает null

Вот код для загрузки блоб

public Stream DownloadBlobAsStream(CloudStorageAccount account, string blobUri) 
{ 
    Stream mem = new MemoryStream(); 
    CloudBlobClient blobclient = account.CreateCloudBlobClient(); 
    CloudBlockBlob blob = blobclient.GetBlockBlobReference(blobUri); 

    if (blob != null) 
     blob.DownloadToStream(mem); 

    return mem; 
} 

И код, чтобы преобразовать его в массив байтов

public static byte[] ReadFully(Stream input) 
    { 
     byte[] buffer = new byte[16 * 1024]; 
     using (MemoryStream ms = new MemoryStream()) 
     { 
      int read; 
      while ((read = input.Read(buffer, 0, buffer.Length)) > 0) 
      { 
       ms.Write(buffer, 0, read); 
      } 
      return ms.ToArray(); 
     } 
    } 

Но я всегда получаю нулевое значение. Ниже приведено содержимое потокового файла.

enter image description here

Что не так с этим? Пожалуйста помоги.

EDIT

Установка положения в 0 внутри ReadFully метода не допускается, так что я положил его в DownloadBlobAsStream

Это должно работать:

public Stream DownloadBlobAsStream(CloudStorageAccount account, string blobUri) 
{ 
    Stream mem = new MemoryStream(); 
    CloudBlobClient blobclient = account.CreateCloudBlobClient(); 
    CloudBlockBlob blob = blobclient.GetBlockBlobReference(blobUri); 

    if (blob != null) 
     blob.DownloadToStream(mem); 
    mem.Position = 0; 
    return mem; 
} 
+0

Существует какое-то недоразумение с вашей стороны, как вы уверены, что можете установить позицию в 0 @ ReadFully однако вы должны использовать «вход» объект. Объект mem имеет локальную область внутри DownloadBlobAsStream(), поэтому, если вы хотите установить mem.Position, это должно быть сделано в этой функции, однако, когда вы вызываете ReadFully() и передаете свой объект Stream, вы можете установить его Position на 0 как ну, как я показал в своем размещении. Поэтому оба принимаются и будут работать. – AvkashChauhan

+0

Если я установил Position = 0 внутри ReadFully, он выдает сообщение об ошибке «Не поддерживается», и когда я пытаюсь посмотреть свойство ввода, «CanSeek = false», но ваша идея очень помогла. :) – fiberOptics

+0

Чтобы уточнить, вы получаете нулевое значение или пустой массив байтов? Я не видел нулевого значения, но видел в моем тестировании пустой массив байтов, не изменяя каким-либо образом положение потока. – kendaleiv

ответ

12

Ваша проблема в том, что ваш указатель потока ввода установлен на конец пара (см. снимок экрана, длина и позиция показывают одинаковое значение), поэтому, когда вы его читаете, вы всегда получаете нуль. Вам нужно будет установить на входной указатель потока на 0, используя Stream.Position = 0, как показано ниже:

public static byte[] ReadFully(Stream input) 
{ 
    byte[] buffer = new byte[16 * 1024]; 

    input.Position = 0; // Add this line to set the input stream position to 0 

    using (MemoryStream ms = new MemoryStream()) 
    { 
     int read; 
     while ((read = input.Read(buffer, 0, buffer.Length)) > 0) 
     { 
      ms.Write(buffer, 0, read); 
     } 
     return ms.ToArray(); 
    } 
} 
+2

Значит ли это, что DownloadToStream на самом деле не соответствует его обещанию? Это вместо того, чтобы позволить пользователю по-настоящему передавать данные из лазурного, что делает почти то же самое, что и DownloadByteArray, поскольку оно заставляет вас читать весь файл в памяти? –

+3

Я думаю, что CloudBlockBlob.OpenRead() можно использовать для получения потока, который может использоваться для доступа к частям блоба без необходимости сначала загружать все это. – user764754

5

Как об использовании метода OpenRead() на объекте CloudBlob?

public static string ReadFully(string blobUri, string itemUri) 
{ 
    // e.g. itemUri == "foo.txt" 
    // if there is a folder "bar" with foo.txt, provide instead: "bar/foo.txt" 
    CloudBlobContainer cloudBlobContainer = new CloudBlobContainer(new Uri(blobUri)); 
    CloudBlob blobReference = cloudBlobContainer.GetBlobReference(itemUri); 

    using (var stream = blobReference.OpenRead()) 
    { 
     using (StreamReader reader = new StreamReader(stream)) 
     { 
      return reader.ReadToEnd(); 
     } 
    } 
} 
0

Я попытался реализации кода выше, но, к моему удивлению, функция GetBlockBlobReference не присутствовала в CloudBlobClient, но в CloudBlockBlob.

Возможно, библиотеки DLL менялись во времени.

Поэтому я представляю вам с моей адаптацией:

public class BlobStorageHelper 
{ 
    private readonly CloudBlobClient _blobClient; 
    protected readonly CloudStorageAccount StorageAccount; 
    public string _containerName { get; set; } 

    public BlobStorageHelper() 

    { 
     _blobClient = base.StorageAccount.CreateCloudBlobClient(); 
     _containerName = ConfigurationManager.AppSettings["StorageContainerName"]; 
     StorageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["StorageConnectionString"]); 
    } 

    protected Stream DownloadBlobAsStream(string blobUri) 
    { 
     CloudStorageAccount account = this.StorageAccount; 
     CloudBlockBlob blob = GetBlockBlobReference(account, blobUri); 

     Stream mem = new MemoryStream(); 
     if (blob != null) 
     { 
      blob.DownloadToStream(mem);     
     } 

     return mem; 
    } 

    private CloudBlockBlob GetBlockBlobReference(CloudStorageAccount account, string blobUri) 
    { 
     string blobName = blobUri.Substring(blobUri.IndexOf("/" + _containerName + "/")).Replace("/" + _containerName + "/", ""); 
     CloudBlobClient blobclient = account.CreateCloudBlobClient(); 
     CloudBlobContainer container = _blobClient.GetContainerReference(_containerName); 
     container.CreateIfNotExists(); 
     CloudBlockBlob blob = container.GetBlockBlobReference(blobName); 
     return blob; 
    } 


    public byte[] DownloadBlobAsByeArray(string blobUri) 
    { 
     Stream inputStream = DownloadBlobAsStream(blobUri); 

     byte[] buffer = new byte[16 * 1024]; 

     inputStream.Position = 0; // Add this line to set the input stream position to 0 

     using (MemoryStream ms = new MemoryStream()) 
     { 
      int read; 
      while ((read = inputStream.Read(buffer, 0, buffer.Length)) > 0) 
      { 
       ms.Write(buffer, 0, read); 
      } 
      return ms.ToArray(); 
     } 
    } 


} 
Смежные вопросы