2012-06-05 24 views
12

Ich versuche, eine Datei aus cloudblob über Stream herunterzuladen. Ich Sie in diesem Artikel CloudBlobCloudBlob.DownloadToStream gibt null zurück

Hier ist der Code den 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; 
} 

Und den Code zum Download es in Byte-Array zu konvertieren

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

Aber ich immer null Wert. Im Folgenden finden Sie den Inhalt der gestreamten Datei.

enter image description here

Was mit diesem ist falsch? Bitte helfen Sie.

EDIT

die Position auf 0 innerhalb ReadFully Methode Einstellung nicht zulässig ist, so habe ich es in DownloadBlobAsStream

Dies sollte jetzt arbeiten:

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

Es gibt einige Missverständnisse auf Ihrer Seite ist, wie Sie sicher Position auf 0 @ readfully einstellen können, aber Sie müssen Objekt „Eingang“ verwenden. Objekt mem hat einen lokalen Bereich in DownloadBlobAsStream() Deshalb, wenn Sie mem.Position setzen wollen, muss es in dieser Funktion gemacht werden, aber wenn Sie ReadFully() aufrufen und Ihr "Stream" -Objekt übergeben, können Sie seine Position auf 0 setzen naja, wie ich es in meinem Posting gezeigt habe. Also beide sind akzeptiert und werden funktionieren. – AvkashChauhan

+0

Wenn ich die Position = 0 in ReadFully einstelle, wird ein Fehler "Nicht unterstützt" ausgegeben, und wenn ich versuche, die Eingabeeigenschaft zu betrachten, ist 'CanSeek = false', aber deine Idee hat mir sehr geholfen. :) – fiberOptics

+0

Nur um zu klären, erhalten Sie einen Null-Wert oder ein leeres Byte-Array? Ich habe keinen Nullwert gesehen, aber in meinem Test ein leeres Byte-Array gesehen, ohne die Stream-Position irgendwie zu ändern. – kendaleiv

Antwort

12

Ihr Problem ist, dass Ihr Der Eingabe-Stream-Zeiger wird auf das Ende des Dampfs gesetzt (siehe Screenshot, Länge und Position zeigen beide den gleichen Wert). Deshalb erhalten Sie beim Lesen immer null. Sie müßten Eingang Stream-Zeiger auf 0 mit Stream.Position = 0 wie unten setzen:

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

Also bedeutet dies, dass DownloadToStream nicht wirklich seine Versprechen hält? Das, anstatt einem Benutzer zu erlauben, die Daten wirklich von azure zu streamen, die gerade fast das selbe tut, wie DownloadByteArray, da es Sie zwingt, die gesamte Datei in Gedächtnis zu lesen? –

+3

Ich denke CloudBlockBlob.OpenRead() kann verwendet werden, um einen Stream zu erhalten, der verwendet werden kann, um auf Teile des Blobs zuzugreifen, ohne dass zuerst das Ganze heruntergeladen werden muss. – user764754

5

Wie sei es mit der Openread() -Methode auf dem CloudBlob Objekt?

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

Ich habe versucht, den Code über die Umsetzung, aber zu meiner Überraschung, die Funktion GetBlockBlobReference war nicht anwesend in CloudBlobClient aber in CloudBlockBlob.

Vielleicht haben sich die DLLs im Laufe der Zeit verändert.

Deshalb präsentieren Sie ich mit meiner Anpassung:

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


}