Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 559
Ben Foster Avatar asked Oct 03 '13 14:10

Ben Foster


People also ask

What is an append blob?

Append blobs are made up of blocks like block blobs, but are optimized for append operations. Append blobs are ideal for scenarios such as logging data from virtual machines.

What is the difference between Block blob and append blob?

Block blobs are composed of blocks and are ideal for storing text or binary files, and for uploading large files efficiently. Append blobs are also made up of blocks, but they are optimized for append operations, making them ideal for logging scenarios.

How do you change a Block blob to a page blob?

You need 2 SAS URLs with addecuate permission to read from the original container and to write to the destination. You also need the LIST permission. Having that, open the Cloud Shell and write the command. After coping, just delete the old page blobs.

What is a CloudBlockBlob?

Description. CloudBlockBlob(final CloudBlockBlob otherBlob) Creates an instance of the class by copying values from another cloud block blob. CloudBlockBlob(final StorageUri blobAbsoluteUri) Creates an instance of the class using the specified absolute StorageUri.


2 Answers

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;
                }
            }
        }
    }
like image 60
Gaurav Mantri Avatar answered Sep 28 '22 09:09

Gaurav Mantri


There is now a CloudAppendBlob class that allows you to add content to an existing blob :

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

In your case you want to append from a stream:

await blob.AppendFromStreamAsync(new MemoryStream());

But you can append from text, byte array, file. Check the documentation.

like image 39
Thomas Avatar answered Sep 28 '22 08:09

Thomas