'Asynchronously Streaming Video with .Net Core API from Azure Blob Storage
I have found a bunch of examples that use objects not available to me within my application and don't seem to match up to my version of .NET Core web API. In essence, I am working on a project that will have tags on a web page and want to load the videos using a stream from the server rather than directly serving the files via a path. One reason is the source of the files may change and serving them via path isn't what my customer wants. So I need to be able to open a stream and async write the video file.
This for some reason produces JSON data so that's wrong. I am downloading the video file from Azure Blob storage and returning as a stream, but I just don't understand what I need to do to send a streamed video file to a tag in HTML.
My API Controller,
[AllowAnonymous]
[HttpGet("getintroductoryvideos")]
public async Task<Stream> GetIntroductoryVideos()
{
try
{
return _documentsService.WriteContentToStream().Result;
}
catch (Exception ex)
{
throw ex;
}
}
My Service class,
public async Task<Stream> WriteContentToStream()
{
var cloudBlob = await _blobService.GetBlobAsync(PlatformServiceConstants._blobIntroductoryVideoContainerPath + PlatformServiceConstants.IntroductoryVideo1, introductoryvideocontainerName);
await cloudBlob.FetchAttributesAsync();
var fileStream = new MemoryStream();
await cloudBlob.DownloadToStreamAsync(fileStream);
return fileStream;
}
Solution 1:[1]
You can try the code below:
API Controller:
[AllowAnonymous]
[HttpGet("getintroductoryvideos")]
public async Task<FileContentResult> GetIntroductoryVideos(string videoname)
{
return await _documentsService.WriteContentToStream();
}
Service class:
public async Task<FileContentResult> WriteContentToStream()
{
var cloudBlob = await _blobService.GetBlobAsync(PlatformServiceConstants._blobIntroductoryVideoContainerPath + PlatformServiceConstants.IntroductoryVideo1, introductoryvideocontainerName);
MemoryStream fileStream = new MemoryStream();
await cloudBlob.DownloadToStreamAsync(fileStream);
return new FileContentResult (fileStream.ToArray(), "application/octet-stream");
}
Html:
<div className="xxx">
<video height="auto">
<source src="xx/getintroductoryvideos?videoname=xxx" type="video/mp4" />
</video>
</div>
Solution 2:[2]
You probably want to avoid loading the entire video in memory before returning it. You should be able to pass through a stream by using FileStreamResult
:
[AllowAnonymous]
[HttpGet("getintroductoryvideos")]
public async Task<IActionResult> GetIntroductoryVideos()
{
var cloudBlob = await _blobService.GetBlobAsync(PlatformServiceConstants._blobIntroductoryVideoContainerPath + PlatformServiceConstants.IntroductoryVideo1, introductoryvideocontainerName);
var stream = await cloudBlob.OpenReadAsync();
return new FileStreamResult(stream, "application/octet-stream");
}
Solution 3:[3]
Here is what I have done. The key point is the last line. The last parameter there enables the range request called EnableRangeProcessing. Although this starts supporting from .net core 2.1 and 2.1 plus.
[AllowAnonymous]
[HttpGet("getintroductoryvideos")]
public async Task<IActionResult> GetIntroductoryVideos()
{
var cloudBlob = await _blobService.GetBlobAsync(PlatformServiceConstants._blobIntroductoryVideoContainerPath + PlatformServiceConstants.IntroductoryVideo1, introductoryvideocontainerName);
var stream = await cloudBlob.OpenReadAsync();
return new File(stream, "application/octet-stream",true);
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Ivan Yang |
Solution 2 | Stephen Cleary |
Solution 3 | Mir Gulam Sarwar |