DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
Securing Your Software Supply Chain with JFrog and Azure
Register Today

Trending

  • Java Concurrency: Condition
  • A Complete Guide to Agile Software Development
  • Authorization: Get It Done Right, Get It Done Early
  • Part 3 of My OCP Journey: Practical Tips and Examples

Trending

  • Java Concurrency: Condition
  • A Complete Guide to Agile Software Development
  • Authorization: Get It Done Right, Get It Done Early
  • Part 3 of My OCP Journey: Practical Tips and Examples
  1. DZone
  2. Software Design and Architecture
  3. Cloud Architecture
  4. Document Versioning With Azure Blob Storage

Document Versioning With Azure Blob Storage

Build your custom Document Library using Azure Blob Storage Versioning. C# helpers to achieve Document versioning, etc.

Subhankar Sarkar user avatar by
Subhankar Sarkar
·
Updated Oct. 12, 20 · Tutorial
Like (2)
Save
Tweet
Share
5.72K Views

Join the DZone community and get the full member experience.

Join For Free

Some Background First

Almost all organizations have a need for document storage for their applications. If the organization is a Microsoft shop then, one of the most popular choices for them is the SharePoint Document Library. SharePoint Document library allows you to store documents, retain their versions, provides the ability to make any old version to the current version, last but not the least deleting a specific version of a document.

With all the goodness of SharePoint, it comes with its own limitations. For many custom cloud, applications build, SharePoint may not always be the right choice because of various reasons. It needs a dedicated setup, licensing, etc. And just to use the document library feature, the investment may not always be justifiable.

So, what option do you have? Can you achieve all the above SharePoint Document Library features otherwise?

If you are building your application in Azure, then it is highly likely that you are taking the benefit of Azure Storage Account Blob Container for any storage needs, including but not limited to document/ file storage.

The good news is you can now achieve all of these using Azure Storage Account’s blob versioning feature.

In this article, I’m going to talk about how you can leverage your existing Azure Storage Account Infrastructure and use it effectively for your document and file storage needs. 

I’m going to cover the following with a few C# code samples. 

  • Document Versioning
  • List all document with all their versions 
  • Download a specific version of the document
  • Make a specific version of the document to the current version
  • Delete a specific version of the document

You can find the entire project in GitHub.

How Can You Achieve Versioning in Blob Storage?

Until this announcement of Blob Versioning for Azure Storage Account, it was tedious to maintain the versions of any document stored as a blob in a container. One such manual approach was to take a snapshot of the document while uploading. Maintain that snapshot information in some sort of table (e.g.: database tables). And to restore the file, use the table stored information to restore from the snapshot.

You can read more about Snapshot and Blob versioning here.

Okay, so those days are gone now. With some simple steps, you can enable versioning to your blob and achieve document library like features.

You can enable Versioning while creating the storage account. Under the Data protection tab check Tracking >> Turn on versioning option.

storage account

For your existing Storage Account, to enable versioning to go to the left side blade >> look for Data Protection under Blob service. On your left pane under Tracking select Turn on versioning

data protection

Now that the blob versioning is enabled, let's see it in action.

Now, Upload a File and See Blob Versioning in Action

To test it out, upload a file with the same name with varying content to the container multiple times. Now find the file in the container which you have just uploaded. You can use the Azure portal to upload the file or use the following code

C#
 




xxxxxxxxxx
1
12


 
1
public async Task<string> UploadBlobAsync(string filePath)
2
{
3
    var blobName = Path.GetFileName(filePath);
4
    string uploadedDocVersion = string.Empty;
5
    using (var ms = new MemoryStream(File.ReadAllBytes(filePath)))
6
    {
7
        var blobClient = BlobContainerClient.GetBlockBlobClient(blobName);
8
        var blob = await blobClient.UploadAsync(ms);
9
        uploadedDocVersion = blob.Value.VersionId;
10
    }
11
    return uploadedDocVersion;
12
}



Click on the View previous versions option. You will see all the versions of the file listed with a timestamp.

doc1.txt

Now let’s write some code to list all the versions of the uploaded files in the container.

Listing All the Versions of an Uploaded File

Blob versioning features can be programmatically accessed using the Azure Storage client library for .NET, version 12.5.1, or later. However, I couldn’t find a way to list down the versions of all the files in the container using this NuGet.

So, I did a little hack. From the Azure Portal – I clicked on the View Previous Versions and I intercepted the REST API URL from the Network tab of developer tools.

Version 2019-10-10 and higher of the Azure Storage REST API supports blob versioning. Using the below code I was able to call the REST API URL. https://{accountname}.blob.core.windows.net/{containername}

?restype=container&comp=list&include=versionsand retrieve all the versions of all the files in the container.

C#
 




x


 
1
public static async Task<List<FileModel>> ListAllDocumentWithVersion(string storageAccountName, string storageAccountKey, string containerName, CancellationToken cancellationToken)
2
{
3
    // I intercepted this url from the Azure Portal. include=versions is doing all the magic here
4
    var uri = string.Format("https://{0}.blob.core.windows.net/{1}?restype=container&comp=list&include=versions", storageAccountName, containerName);
5
    Byte[] requestPayload = null;
6

           
7
    using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, uri) { Content = (requestPayload == null) ? null : new ByteArrayContent(requestPayload) })
8
    {
9
        // Add the request headers for x-ms-date and x-ms-version.
10
        var now = DateTime.UtcNow;
11
        httpRequestMessage.Headers.Add("x-ms-date", now.ToString("R", CultureInfo.InvariantCulture));
12
        httpRequestMessage.Headers.Add("x-ms-version", "2019-12-12");
13

           
14
        // Add the authorization header.
15
        httpRequestMessage.Headers.Authorization = AzureStorageAuthHelper.GetAuthorizationHeader(
16
           storageAccountName, storageAccountKey, now, httpRequestMessage);
17

           
18
        // Send the request.
19
        var allFiles = new List<FileModel>();
20
        using (var httpResponseMessage = await new HttpClient().SendAsync(httpRequestMessage, cancellationToken))
21
        {
22
            //   parse the XML response for the container names.
23
            if (httpResponseMessage.StatusCode == HttpStatusCode.OK)
24
            {
25
                var xmlString = await httpResponseMessage.Content.ReadAsStringAsync();
26
                var x = XElement.Parse(xmlString);
27

           
28
                foreach (XElement container in x.Element("Blobs").Elements("Blob"))
29
                {
30
                    string fileName = container.Element("Name").Value;
31

           
32
                    var model = new FileModel() { FileName = container.Element("Name").Value, FileVersion = container.Element("VersionId").Value };
33
                    allFiles.Add(model);
34
                }
35
            }
36
        }
37
        return allFiles;
38
    }
39
}



Downloading a Specific Version

To download a specific version of a file use WithVersion. This line var blob = blobClient.WithVersion(fileVersion); in the code below is doing all the magic.

C#
 




xxxxxxxxxx
1
11


 
1
public async Task<byte[]> DownloadBlobAsync(string fileToDownload, string fileVersion)
2
{
3
    using (var ms = new MemoryStream())
4
    {
5
        var blobClient = BlobContainerClient.GetBlockBlobClient(fileToDownload);
6
        // WithVersion() is the key piece here
7
        var blob = blobClient.WithVersion(fileVersion);
8
        await blob.DownloadToAsync(ms);
9
        return ms.ToArray();
10
    }
11
}



Restoring a File To a Specific Version

One of the most important functionalities if any document library is to restore any file version and make it as the current version. To restore to a specific version, you have to use the copy blob function. I found StartCopyFromUri very helpful since I could pass the VersionId of the file with the blob url query parameter as https://{0}.blob.core.windows.net/{1}/{2}?versionid={3} 

C#
 




xxxxxxxxxx
1
13


 
1
public void RestoreFileToSpecificVersion(string storageAccountName, string containerName, string fileName, string sourceVersion)
2
{
3
    var blobClient = BlobContainerClient.GetBlockBlobClient(fileName); // this is pointing to the current version
4
    //versionid={} is the most important piece here
5
    var sourceBlobUri = new Uri(
6
        string.Format("https://{0}.blob.core.windows.net/{1}/{2}?versionid={3}",
7
        storageAccountName, containerName, fileName, sourceVersion));
8

           
9
    // Since it will copy in the same storage account's container, it's a synchronous process
10
    // Copy Operation will make the specic version as current version
11
    // See https://docs.microsoft.com/en-us/rest/api/storageservices/copy-blob-from-url#request-headers
12
    blobClient.StartCopyFromUri(sourceBlobUri);
13
}



Deleting a Specific Version

Last but not the least, you can delete a specific version of a file from the storage container. Again .WithVersion will help you here to delete a specific version as below.

C#
 




xxxxxxxxxx
1


 
1
public async Task DeleteSpecificVersion(string fileName, string versionToDelete)
2
{
3
    // WithVersion() is the key piece here
4
    var blobClient = BlobContainerClient.GetBlockBlobClient(fileName).WithVersion(versionToDelete);
5
    await blobClient.DeleteAsync();
6
}



Wrap Up

In this post, I have covered a few key features of a Document library which you can achieve with Azure Blob Versioning and a few lines of code. This solution is not meant to replace SharePoint or any other document management solutions. I felt this would become very handy to retain document versions, restore a document, delete a specific version of a custom build application that uses Azure Storage Account as storage infrastructure.

Document azure Database Container Library

Published at DZone with permission of Subhankar Sarkar. See the original article here.

Opinions expressed by DZone contributors are their own.

Trending

  • Java Concurrency: Condition
  • A Complete Guide to Agile Software Development
  • Authorization: Get It Done Right, Get It Done Early
  • Part 3 of My OCP Journey: Practical Tips and Examples

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com

Let's be friends: