Search code examples
azureazure-storageazure-blob-storage

Append to CloudBlockBlob stream


We have a file system abstraction that allows us to easily switch between local and cloud (Azure) storage.

For reading and writing files we have the following members:

Stream OpenRead();
Stream OpenWrite();

Part of our application "bundles" documents into one file. For our local storage provider OpenWrite returns an appendable stream:

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

For Azure blob storage we do the following:

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

Unfortunately this overrides the blob contents each time. Is it possible to return a writable stream that can be appended to?


Solution

  • Based on the documentation for OpenWrite here 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.

    One thing you could do is read the blob data in a stream and return that stream to your calling application and let that application append data to that stream. For example, see the code below:

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