2012-06-05 20 views
12

Próbuję pobrać plik z CloudBlob przez strumień. Odsyłam do tego artykułu CloudBlobCloudBlob.DownloadToStream zwraca null

Oto kod, aby pobrać blob

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; 
} 

a kod aby przekształcić go w bajt tablicy

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(); 
     } 
    } 

ale zawsze wartość zerową. Poniżej znajduje się zawartość przesyłanego pliku.

enter image description here

Co jest nie tak z tym? Proszę pomóż.

EDIT

Ustawienie stanowiska, jakie 0 wewnątrz ReadFully metody nie jest dozwolone, więc umieścić go wewnątrz DownloadBlobAsStream

To powinno działać teraz:

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

Istnieją pewne nieporozumienie z twojej strony, jak na pewno można ustawić stanowisko 0 @ ReadFully jednak trzeba użyć „Input” obiekt. Pamięć obiektu ma zasięg lokalny wewnątrz funkcji DownloadBlobAsStream(), dlatego jeśli chcesz ustawić wartość mem.Position, należy to zrobić w tej funkcji, jednak gdy wywołasz ReadFully() i przekazujesz obiekt "Stream", możesz ustawić jego pozycję na 0 jako cóż, jak pokazałem w moim poście. Więc oba są akceptowane i będą działać. – AvkashChauhan

+0

Jeśli ustawię Position = 0 wewnątrz ReadFully, spowoduje to błąd "Not Supported", a kiedy spróbuję spojrzeć na właściwość input, 'CanSeek = false', ale twój pomysł bardzo pomógł. :) – fiberOptics

+0

Aby wyjaśnić czy otrzymujesz wartość pustą lub pustą tablicę bajtów? Nie widziałem wartości pustej, ale widziałem pustą tablicę bajtów w moich testach bez jakiejkolwiek zmiany pozycji strumienia. – kendaleiv

Odpowiedz

12

Twoim problemem jest to, że wskaźnik strumienia wejściowego jest ustawiony na koniec pary (zobacz zrzut ekranu, długość i pozycja pokazują tę samą wartość), dlatego podczas czytania zawsze dostajemy wartość zerową. trzeba by ustawić wejściowego strumienia wskaźnik do 0 za pomocą Stream.Position = 0 jak poniżej:

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

Czy to oznacza, że ​​DownloadToStream faktycznie nie spełnia obietnicy? Że zamiast pozwolić użytkownikowi naprawdę wypromować dane z lazuru, które właśnie robią prawie to samo co DownloadByteArray, ponieważ zmusza cię do przeczytania całego pliku w pamięci? –

+3

Myślę, że CloudBlockBlob.Funkcja OpenRead() może być wykorzystana do uzyskania strumienia, który może być użyty do uzyskania dostępu do części obiektu typu blob bez konieczności pobierania całości. – user764754

5

Jak o użyciu metody OpenRead() na obiekcie 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

Próbowałem realizacji powyższy kod, ale ku mojemu zdziwieniu, funkcja GetBlockBlobReference nie był obecny w CloudBlobClient ale w CloudBlockBlob.

Być może biblioteki DLL uległy zmianie w czasie.

Dlatego przedstawiam ci mojego dostosowania:

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(); 
     } 
    } 


}