Does Azure Blob Storage supports partial content 206 by default?

Viewed 2682

I am using Azure blob storage to storage all my images and videos. I have implemented the upload and fetch functionality and it's working quite good. I am facing 1 issue while loading the videos, because when I use the url which is generated after uploading that video on Azure blob storage, it's downloading all the content first before rendering it to the user. So if the video size is 100 mb, it'll download all the 100 mb and till than user won't able to see the video.

I have done a lot of R&D and came to know that while rendering the video, I need to fetch the partial content (status 206) rather than fetching the whole video at a time. After adding the request header "Range:bytes-500", I tried to hit the blog url, but it's still downloading the whole content. So I have checked with some open source video URLs and tried to hit the video URL along with the "Range" request header and it was successfully giving 206 response status, which means it was properly giving me the partial content instead of the full video.

I read some forum and they are saying Azure storage supports the partial content concept and need to enable it from the properties. But I have checked all the options under the Azure storage account but didn't find anything to enable this functionality.

Can anyone please help me out to resolve this or if there's anything on Azure portal that I need to enable? It's something that I have been doing the R&D for this since a week now. Any help would be really appreciated.

Thank you! Stay safe.

3 Answers

Suppose the Accept-Ranges is not enabled, from this blog I got it needs to set the default version of the service.

Below is a sample code to implement it.

            var credentials = new StorageCredentials("account name", "account key");
            var account = new CloudStorageAccount(credentials, true);
            var client = account.CreateCloudBlobClient();
            var properties = client.GetServiceProperties();
            properties.DefaultServiceVersion = "2019-07-07";
            client.SetServiceProperties(properties);

Below is a return header comparison after setting the property.

Before:

enter image description here

After:

enter image description here

Assuming the video content is MPEG-4 the issue may be the media itself needs to have the moov atom position changed from the end of the file to the beginning. The browser won't render the video until it finds the moov atom in the file therefore you want to make sure the atom is at the start of the file which can be accomplished using ffmpeg with the "FastStart". Here's a good article with more detail : HERE

following is the SDK I used to download the contents:

var container = new BlobContainerClient("UseDevelopmentStorage=true", "sample-container");
await container.CreateIfNotExistsAsync();
BlobClient blobClient = container.GetBlobClient(fileName);
Stream stream = new MemoryStream();
var result = await blobClient.DownloadToAsync(stream, cancellationToken: ct);

which DOES download the whole file right away! Unfortunately the solution provided in other answers seems to be referencing another SDK? So for the SDK that I use - the solution is to use the method OpenReadAsync:

        long kBytesToReadAtOnce = 300;
        long bytesToReadAtOnce = kBytesToReadAtOnce * 1024;
        //int mbBytesToReadAtOnce = 1;
        var result = await blobClient.OpenReadAsync(0, bufferSize: (int)bytesToReadAtOnce, cancellationToken: ct);

By default - it fetches 4mb of data, so you have to override the value to smaller amount if you want your app to have smaller memory footprint.

I think that internally the SDK sends the requests with the byte range already set. So all you have to do is enable the partial content support in Web API like this:

        return new FileStreamResult(result, contentType)
        {
            EnableRangeProcessing = true,
        };
Related