OdeToCode IC Logo

Streaming Content in ASP.NET Core

Tuesday, January 9, 2018

I've seen people working hard to stream content in ASP.NET Core. The content could be a video file or other large download. The hard work usually involves byte arrays and memory streams.

Some of this hard work was necessary in 1.0, but there are a number of features in 2.0 that make the extra work unnecessary.

With Static Files

The ASP.NET static files middleware will add ETag headers and can respond to partial range requests. The transfer is efficient.  Here's a cURL request for bytes 0 to 10 of a file named sample.mp4 that lives in the wwwroot folder.

$ curl -sD - -o /dev/null -H "Range: bytes=0-10" localhost:51957/sample.mp4

HTTP/1.1 206 Partial Content
Content-Length: 11
Content-Type: video/mp4
Content-Range: bytes 0-10/10630899
Last-Modified: Wed, 14 May 2014 23:39:15 GMT
Accept-Ranges: bytes
ETag: "1cf6fcdb79b6573"

In the output you can see the 206 partial content response and Accept-Ranges header.

With File Results

There are many scenarios where serving files with static files middleware is problematic. One scenario is when the files require authorization checks. It is possible to enforce authorization checks on static files, but another approach is to use controller actions. Imagine serving up the following HTML:

<h2>File Stream</h2>
<video autoplay controls src="/stream/samplevideo"></video>

The video source points to the following controller action.

[Authorize(Policy = "viewerPolicy")]
public IActionResult SampleVideoStream()
{
    var path = Path.Combine(pathToVideos, "sample.mp4");
    return File(System.IO.File.OpenRead(path), "video/mp4");
}

FileStreamResult and VirtualFileResult also support Range headers with a 206 response, although they won't send ETags without using some additional code. In  many cases, however, the behavior is good enough to move forward without creating a lot of additional work.


Comments
Gravatar Panos Tuesday, February 6, 2018
Dear mr. Allen, I tries your code which works. I noticed though if for example i have an mp3 file for http://localhost/api/audio/2, when i click on t twice it lags. Can we stream chunks of data through asp.net core? Could you advise why this happens?
Gravatar scott Wednesday, February 7, 2018
Yes, the accept-ranges will send chunks. What browser does this happen in?
Gravatar Panos Thursday, February 8, 2018
Well the primary browser that i am testing is Mozilla. I'm having similar behavior to chrome and IE 11. What my end goal is to play the same song over to the users concurrently. I am having trouble finding material for streaming over asp.net core. using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { return File(fileStream, "audio/mpeg"); } This is the code that i am working with. The api when called for a second time, it sort of loads and loads until the first one is done.
Gravatar scott Monday, February 12, 2018
I can't reproduce the problem (see https://imgur.com/a/vvRGa). I'm surprised your code serves any content with the using statement in place. The using statement will close the file before the FileResult has a chance to write into the response.
Comments are closed.