ASP.NET Core API: Returning Video File as stream and playing video stream in Angular Client Application

In this article, we explore an implementation that involves serving a video file from an ASP.NET Core API as a stream and playing it within an Angular client application. Our goal is to demonstrate how to create a stream response from the API and seamlessly deliver it to the client. During the development of server-side APIs, we often encounter scenarios where users need to download files in client applications. However, when dealing with large files, it’s more efficient to use streamed responses. For instance, if the file is a video, rather than downloading it to the client, we can directly play it in the video player within the client application.

In ASP.NET Core, the FileStreamResult object is utilized to write stream data to the response. This approach allows sending binary content using a Stream instance when returning a file as a FileStream. Figure 1 illustrates the high-level implementation concept.



Figure 1: ASP.NET Core API returning Stream to Angular Client


Step 1: Create an ASP.NET Core API Project in Visual Studio 2022

  1. Open Visual Studio 2022.
  2. Create a new ASP.NET Core API project targeted to .NET 8.
  3. Name this project “StreamerAPI.”
  4. Within the project, add a new folder named “VideoServer.”
  5. Add a couple of video files to this folder. Ensure that the video file extensions are ‘.mp4’.

Step 2: Create a StreamController in the Controllers Folder

  1. In the Controllers folder of your ASP.NET Core API project, add a new Empty API Controller named ‘StreamController’.
  2. Within this controller, we’ll define two action methods:
    • GetFiles(): This method will return a list of all available videos in the ‘VideoServer’ folder.
    • Get(): The Get() method will accept a file name from the client. Based on the received file name, it will read the corresponding video file from the ‘VideoServer’ folder and stream it as a response using the FileStreamResult object.

Listing 1 shows the code snippet for the controller


using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
 

namespace StreamerAPI.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class StreamController : ControllerBase
    {

        private readonly string _videoFolderPath = "VideoServer"; // Path to the video folder

        [HttpGet]
        [ActionName("files")]
        public IActionResult GetFiles()
        {
            // Logic to retrieve a list of video files in the folder
            var videoFiles = Directory.GetFiles(_videoFolderPath, "*.mp4");
            var fileNames = new List<string>();
            foreach (var file in videoFiles)
            {
                fileNames.Add(Path.GetFileName(file));
            }
            return Ok(fileNames);
        }

        [HttpGet]
        [ActionName("video")]
        public IActionResult Get(string fileName)
        {
            var filePath = Path.Combine(_videoFolderPath, fileName);

            if (System.IO.File.Exists(filePath))
            {
                // Stream the video file as a response
                var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
                return new FileStreamResult(stream, "video/mp4");
            }
            else
            {
                return NotFound($"Video file '{fileName}' not found.");
            }
        }  
    }
}

Listing 1: The StreamerController

We have created a controller that includes methods to retrieve video file names and stream the actual video content.  

Step 3: Create an Angular Application

  1. Open the command prompt.
  2. Create a new Angular application by running the following command:

ng new ng-video-app
Step 4: Create an Angular Service for Video Handling
  1. In your Angular application, create a new Angular service named VideoService.
  2. Within this service, write code to call the StreamController in your ASP.NET Core API and retrieve a list of video file names.
  3. You can use this service to manage video-related functionality within your Angular app.
The code in Listing 2 shows an implementation of the VideoService.

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class VideoService {
  private url:string;
  constructor(private http:HttpClient) {
    this.url = "https://localhost:7212/api/Stream";
  }
  
  getFiles():Observable<string[]> {
    let result:Observable<string[]>;
    result = this.http.get<string[]>(`${this.url}/files`);
    return result;
  }
}

Listing 2: The VideoService 

Step 5: Enhance AppComponent to Stream Video Files

  1. In your app.component.ts file, modify the AppComponent class to include the following features:
    • Access the getFiles() method from the VideoService.
    • Invoke the getFiles() method in the ngOnInit() lifecycle hook.
    • Declare a videoPlayer element reference using @ViewChild. This reference will be used to interact with the HTML5 video element for playing videos.
    • Implement the OnSelectedVideo() method, which accepts the selected file as an input parameter.
    • Inside the OnSelectedVideo() method, create an HTTP URL to access the get() method of the API for requesting the video stream.
    • Assign this URL to the src property of the video element.
    • Once done, the stream received from the API will be played in the video player within the browser.
    
The code of the AppComponent is shown in Listing 3
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { VideoService } from './video.service';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css'
})
export class AppComponent implements OnInit {
  @ViewChild("videoPlayer", { static: false })
  videoPlayer!: ElementRef;
   files:string[];
   message:string;
   fileName:string;
   constructor(private serv:VideoService){
    this.files = [];
    this.message = '';
    this.fileName = '';
   }
  ngOnInit(): void {
    this.serv.getFiles()
        .subscribe({
          next:(resp)=>{
            this.files = resp
          },
          error:(err)=>{
            this.message = `Error Occurred : ${err}`
          }
        });
  }

  onSelectedVideo(file:string):void {

     this.fileName = `https://localhost:7212/api/Stream/video?fileName=${file}`;

     this.videoPlayer.nativeElement.src = this.fileName;
     this.videoPlayer.nativeElement.play();
  }

}
Listing 3: The AppComponent

Step 6: Update the app.component.html File

Replace the existing code in your app.component.html file with the HTML snippet provided in Listing 4.

<h1>Video Library</h1>

<div class="container">
  <table class="table table-bordered">
     <tbody>
      <tr>
        <td>
          <div>
             <ul>
              @for(file of files; track $index) {
                <li (click)="onSelectedVideo(file)">{{file}}</li>
              }
             </ul>
          </div>
        </td>
        <td>
          <video autoplay style="height: 300px;width: 400px;" controls #videoPlayer>
            <source
              type="video/mp4" />
          </video>
        </td>
      </tr>
     </tbody>
  </table>
</div>

Listing 4: The AppComponent's User Interface

Step 7: Configure HttpClient in Angular

If you’re using Angular 17 and need to configure the HttpClient for making HTTP calls, follow the instructions below:

  1. Locate the app.config.ts file in your Angular project.
  2. Modify the code to use the provideHttpClient as demonstrated in Listing 5.
  3. This configuration ensures that your Angular application can effectively use the HttpClient module for handling HTTP requests.


export const appConfig: ApplicationConfig = {
  providers: [provideRouter(routes),
   provideHttpClient()
  ]
};
Listing: Registration for HttpClient
Once you run the API and Angular application, navigate to the URL http://localhost:4200 in your browser. The browser will display a list of video files retrieved from the API. When you select any video file, it will be played in the video player, as demonstrated in Figure 2.


Figure 2: The Result 

Conclusion: The ASP.NET Core FileStreamResult is the best way to download the streamed response.

 

Popular posts from this blog

Uploading Excel File to ASP.NET Core 6 application to save data from Excel to SQL Server Database

ASP.NET Core 6: Downloading Files from the Server

ASP.NET Core 6: Using Entity Framework Core with Oracle Database with Code-First Approach