2012-06-05 16 views
12

Sto provando a scaricare un file da cloudBlob tramite streaming. Mi riferisco a questo articolo CloudBlobCloudBlob.DownloadToStream restituisce null

Ecco il codice per scaricare il 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; 
} 

E il codice per convertirla in array di byte

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

ma ottengo sempre valore nullo. Di seguito è il contenuto del file in streaming.

enter image description here

Cosa c'è di sbagliato con questo? Per favore aiuto.

EDIT

Impostazione della posizione a 0 dentro ReadFully metodo non è consentito, così ho messo dentro DownloadBlobAsStream

questo dovrebbe funzionare ora:

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

C'è un malinteso da parte vostra, come si sicuro possibile impostare Posizione a 0 @ ReadFully tuttavia è necessario utilizzare l'oggetto "Ingresso". L'oggetto mem ha un ambito locale all'interno di DownloadBlobAsStream() ecco perché se si desidera impostare mem.Position, è necessario farlo in questa funzione, tuttavia, quando si chiama ReadFully() e si passa l'oggetto "Stream", è possibile impostare la sua posizione su 0 come bene, come ho mostrato nel mio post. Quindi entrambi sono accettati e funzioneranno. – AvkashChauhan

+0

Se imposto Position = 0 all'interno di ReadFully, genera un errore "Not Supported", e quando provo a guardare la proprietà di input, 'CanSeek = false', ma la tua idea ha aiutato molto. :) – fiberOptics

+0

Giusto per chiarire stai ottenendo un valore nullo o un array di byte vuoto? Non ho visto un valore nullo, ma ho visto un array di byte vuoto nei miei test senza in qualche modo modificare la posizione del flusso. – kendaleiv

risposta

12

Il tuo problema è che la vostra il puntatore del flusso di input è impostato alla fine del vapore (Vedi la schermata, Lunghezza e Posizione mostrano entrambi lo stesso valore) ecco perché quando lo leggi, ottieni sempre nulla. Si avrebbe bisogno di impostare l'input del puntatore flusso a 0 utilizzando Stream.Position = 0 come di seguito:

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

Quindi questo implica che DownloadToStream non sia all'altezza delle sue promesse? Quello invece di permettere a un utente di fare il vero streaming dei dati da azzurro che sta facendo quasi la stessa cosa di DownloadByteArray dato che ti costringe a leggere l'intero file in memoria? –

+3

Penso che CloudBlockBlob.OpenRead() può essere utilizzato per ottenere un flusso che può essere utilizzato per accedere a parti del BLOB senza dover prima scaricare il tutto. – user764754

5

Come sull'utilizzo del metodo OpenRead() sull'oggetto 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

Ho provato l'attuazione del codice di cui sopra, ma con mia sorpresa, la funzione GetBlockBlobReference non era presente in CloudBlobClient ma in CloudBlockBlob.

Forse le DLL sono cambiate nel tempo.

Perciò io vi presenti con il mio adattamento:

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


}