2013-10-03 12 views
6

Mamy abstrakcję systemu plików, która pozwala nam łatwo przełączać się między lokalną i chmurową (Azure) pamięcią masową.Dołącz do strumienia CloudBlockBlob

do odczytu i zapisu plików mamy następujący członkowie:

Stream OpenRead(); 
Stream OpenWrite(); 

częścią naszej aplikacji „wiązek” dokumentów w jednym pliku. Dla naszego lokalnego dostawcy przechowywania OpenWrite zwraca strumień appendable:

public Stream OpenWrite() 
{ 
    return new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite, BufferSize, useAsync: true); 
} 

Dla Azure BLOB możemy wykonać następujące czynności:

public Stream OpenWrite() 
{    
    return blob.OpenWrite(); 
} 

Niestety ta nadpisuje zawartość blob każdym razem. Czy można zwrócić zapisywalny strumień, do którego można dołączyć?

Odpowiedz

5

podstawie dokumentacji OpenWrite tutaj http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storage.blob.cloudblockblob.openwrite.aspx, The OpenWrite method will overwrite an existing blob unless explicitly prevented using the accessCondition parameter.

Jedno można zrobić jest odczytać dane blob w strumieniu i powrót tego strumienia do aplikacji wywołującej i pozwól, że aplikacja dołączyć dane do tego strumienia. Na przykład, patrz poniższy kod:

static void BlobStreamTest() 
    { 
     storageAccount = CloudStorageAccount.DevelopmentStorageAccount; 
     CloudBlobContainer container = storageAccount.CreateCloudBlobClient().GetContainerReference("temp"); 
     container.CreateIfNotExists(); 
     CloudBlockBlob blob = container.GetBlockBlobReference("test.txt"); 
     blob.UploadFromStream(new MemoryStream());//Let's just create an empty blob for the sake of demonstration. 
     for (int i = 0; i < 10; i++) 
     { 
      try 
      { 
       using (MemoryStream ms = new MemoryStream()) 
       { 
        blob.DownloadToStream(ms);//Read blob data in a stream. 
        byte[] dataToWrite = Encoding.UTF8.GetBytes("This is line # " + (i + 1) + "\r\n"); 
        ms.Write(dataToWrite, 0, dataToWrite.Length); 
        ms.Position = 0; 
        blob.UploadFromStream(ms); 
       } 
      } 
      catch (StorageException excep) 
      { 
       if (excep.RequestInformation.HttpStatusCode != 404) 
       { 
        throw; 
       } 
      } 
     } 
    } 
+0

Tak właśnie zrobiłem. Zalecanym podejściem wydaje się być 'CloudBlockBlob.PutBlock', ale polegamy na bibliotece PDF, aby wykonać nasze" pakowanie ", które działa tylko z pojedynczym strumieniem wejściowym. –

+1

'CloudBlockBlob.PutBlock' jest zalecany, ponieważ jeśli plik stanie się duży, to powyższe podejście nie będzie wydajne, ponieważ pobierasz cały obiekt typu blob i przesyłasz go ponownie. W "PutBlock" przesyłasz tylko dołączoną część. –

+0

Tak, to jest poważną wadą * zastępowania * obiektu typu blob za każdym razem. Jednak, jak wspomniano, jesteśmy ograniczeni naszą biblioteką PDF. Możemy spojrzeć na buforowanie lokalnej kopii obiektu blob, jeśli stanie się to problemem. –

0

Istnieje obecnie CloudAppendBlob klasa, która pozwala na dodawanie treści do istniejącej blob:

var account = CloudStorageAccount.Parse("storage account connectionstring"); 
var client = account.CreateCloudBlobClient(); 
var container = client.GetContainerReference("container name"); 
var blob = container.GetAppendBlobReference("blob name"); 

W twoim przypadku chcesz dołączyć ze strumienia:

await blob.AppendFromStreamAsync(new MemoryStream()); 

Ale można dodać z tekstu, tablicy bajtów, pliku. Sprawdź dokumentację.