Azure Blob Storage: Streaming the Azure Blob Storage Videos using Shared Access Signature (SAS) Token in the Blazor Web Application
In this article, we will implement an access of the Videos stored in Azure Blob Storage using SAS Tokens and play these videos in Blazor Server Applications without downloading them. The Azure Blob Storage is a scalable, cost-effective, and secure object storage solution for the cloud. We can storage binary files like documents, videos, spreadsheets, etc. in Blob storage and we can access them as on when we need it. The scalability feature of Blob storage helps to store and access large amount of unstructured data that is encrypted at rest and in transit using Microsoft Entra ID as well as with Role-Based Access Control. The Blob storage offer Durability that is designed with geo-replication options. The Blob storage offers Multiple storage tiers like Hot, Cool, and Archive to optimize costs based on data access patterns.
The Common Uses of Blob Storage are as follows:
- Data Lake for Data analytics needs.
- Content Storage and Delivery to serve documents, media files as well as images directly to users.
- Backup and Restore of data for disaster recovery.
- Big Data Analytics uses to store and analyze large datasets with Azure Data Lake
- User Delegation SAS
- This is secured with Microsoft Entra Credentials that offers superior security. This is applied to Blob Storage only
- Service SAS
- This is secured with the storage account key; this delegates access to a specific resource withing one of the Azure Storage services.
- Account SAS
- Like Service SAS, this also secured with the storage account key. This delegates access to resources across multiple services within the storage account.
To create a SAS token, we must use the Azure.Storage.Blobs package in the .NET Client project. This package offers the BlobSasBuilder class. This class has a constructor that access following two parameters:
- BlobContainerSasPermissions enumeration, this contains list of permissions that can be set for a Blob's access policy e.g. Read, Add, Create, Write, etc.
- DateTimeOffset, this is used to define the time at which the SAS token becomes invalid
- BlobContainerName: This represents the name of the Blob container that is being accessible
- BlobName: The name of the Blob being accessible
- Resource: The resource that is being accessible via the SAS Token. If the shared resource is Blob, then the value for this property is "b". The value can be "c" if it is the Blob Container name.
To play the Video files from the Azure Blob Storage, we will use the Blazor Web App. This is a Server controlled Blazor Application Template.
To create and use Azure Blob storage you must have Azure subscription. To use the Azure Blob Storage, we must create a Storage Account that offers Access Key to access the Blob container created in Storage Account. I have already published articles to upload files in Blob storage, these can be read from following links:
Microsoft Azure Storage Blob: Download multiple Blobs from the Azure Storage Blob Containers using SemaphoreSlim Class
Blazor Web Assembly with .NET 6: Uploading File to Azure BLOB Storage
Follow steps explained in above articles to create Storage Account named 'channelvideos' and to create Azure Blob Storage, create a container named 'videos' as shown in Figure 1:
Figure 1: The Storage Account and Container
In the Videos container add media files, I have used ".mp4" files. From the Access Keys section copy the Connection string as shown in Figure 2. Paste the Connection String in Notepad so that we can use it.
Figure 2: The Connection String for the Storage Account
Let's create a client application.
Step 1: Open Visual Studio and create a Blazor Web Application. Name this application as Blazor_VideoStreamBlob. In this project add Azure.Storage.Blobs package. In the appsettings.json file add new keys for the Storage Account Connection String and Blob Name as shown in Listing 1.
"AzureStorageSettings": {
"BLOB_CONNECTION_STRING": "[CONNCTION-STRING]",
"BLOB_CONTAINER_NAME": "videos"
}
Listing 1: The Connection String and Blob Container Name
In this project add a new folder named Infrastructure. In this folder add a new class file name BLOBConnect.cs. In this class file, we will add code for creating SAS Token using the BlobSasBuilder class. The code is shown in Listing 2.
using Azure.Storage.Blobs; using Azure.Storage.Blobs.Models; using Azure.Storage.Sas; namespace Blazor_VideoStreamBlob.Infrastructure { public class BLOBConnect(IConfiguration configuration) { private readonly string? _connectionString = configuration.GetSection("AzureStorageSettings:BLOB_CONNECTION_STRING").Value; private readonly string? _containerName = configuration.GetSection("AzureStorageSettings:BLOB_CONTAINER_NAME").Value; public async Task<string> GetBlobSasToken(string blobName) { var blobSvcClient = new BlobServiceClient(_connectionString); var containerClient = blobSvcClient.GetBlobContainerClient(_containerName); var blobClient = containerClient.GetBlobClient(blobName); var sasBuilder = new BlobSasBuilder(BlobContainerSasPermissions.Read, DateTimeOffset.UtcNow.AddMinutes(15)) { BlobContainerName = _containerName, BlobName = blobName, Resource = "b", }; await containerClient.SetAccessPolicyAsync(PublicAccessType.None); var sasToken = blobClient.GenerateSasUri(sasBuilder).Query; return await Task.FromResult( $"{blobClient.Uri}{sasToken}"); } // code to list all blobs in a container public List<string> ListBlobs() { var blobSvcClient = new BlobServiceClient(_connectionString); var containerClient = blobSvcClient.GetBlobContainerClient(_containerName); var blobs = containerClient.GetBlobs().Select(b => b.Name).Where(b => b.EndsWith(".mp4")).ToList(); return blobs; } } }
Listing 2: The BLOBConnect class
The BLOBConnect class, reads the connection string and container name from the appsettings.json using the IConfiguration interface. The method ListBlobs() uses the BlobServiceClient class to read all blobs having extension as ".mp4". The GetBlobSasToken() method access the blob name as input parameter. This method is used to generate SAS token for this blob using the BlobSasBuilder class. The permission is set to Read, and the expiry is set to 15 minutes. The GenerateSasUri() method of the BlobClient class accepts an instance of the BlobSasBuilder class. This method generates the Uri based SAS Token. This token will be further used to access the BLOB.
Step 2: In the Pages folder of the project, add a new Razor component named BlobStreamer.razor. In this component we will use the HTML Video tag to play the Video from the Blob storage. In this component, we will inject the BLOBConnect class. In this component we will access the ListBlobs() method from the BLOBConnect class to show list of mp4 blobs. We will show all these blobs in the radio buttons by generating them using the List of blobs. The HTML Markup and the code for this component is shown in Listing 3.
@page "/blobstreamer" @rendermode InteractiveServer @inject HttpClient Http @inject Blazor_VideoStreamBlob.Infrastructure.BLOBConnect blobConnect <h3>BLOB Video Streaming using SAS Token</h3> <div class="container"> <div class="row"> <div class="col-md-6 border-3 border-primary list-group"> @foreach (var video in Videos) { <input type="radio" value="@video" name="r" @onclick="@(() => OnVideoSelected(video))"/> <label class="form-check-label" for="r"> @video </label> <br /> } </div> <div class="col-md-6"> @if (!string.IsNullOrEmpty(VideoUrl)) { <video width="600" controls autoplay> <source src="@VideoUrl" type="video/mp4"> Your browser does not support the video tag. </video> } else { <p>Loading video...</p> } </div> </div> </div>
@code { public List<string> Videos { get; set; } = new List<string>(); public string VideoUrl { get; set; } = string.Empty; public string selectedVideo { get; set; } = string.Empty; protected override void OnInitialized() { Videos = blobConnect.ListBlobs(); } private async Task OnVideoSelected(string value) { VideoUrl = ""; selectedVideo = value; var sasToken = await blobConnect.GetBlobSasToken(selectedVideo); VideoUrl = sasToken; } }
Listing 3: The Component code
As shown in Listing 3, the OnVideoSelected() method will be executed when the radio button for a file is selected, this will call the GetBlobSasToken() method of the BLOBConnect class. This method returns the Blob URL that is assigned to the VideoUrl property that is bound to the Vide tag.
We have set the rendermode for the component to InteracctiveServer so that the interactive events like @onclick event on the radio button to access the URI based SAS token for a selected Blob so that it can play in the Video tag.
Step 3: Modify the App.razor to prevent the right-click event on the component as shown in Listing 4.
<script> document.addEventListener('contextmenu', function (event) { event.preventDefault(); }); </script>
Listing 4: Prevent the right-click
This is an important step to make sure that the Video URL cannot be copied by right-clicking on the video.
Step 4: Modify the NavMenu.razor by adding the navigation link for the blobstreamer component which we have added in Step 2. The code in shown in Listing 5.
<div class="nav-item px-3"> <NavLink class="nav-link" href="blobstreamer"> <span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> E-Learner </NavLink> </div>
Listing 5: Navigation
Run the application and click on the E-Learner link, this will render the blobstreamer component that shows the list of Blobs, when a radio button is clicked for blob, it will start playing in the video tag as shown in Figure 3.
Figure 3: The Result
This is how the Blob from the Azure Blob Storage can be directly played in the client application. The code for this article can be downloaded from this link.