Trouble Streaming Video Files [Error:416 Range Not Satisfiable] (ASP.NET/Angular)
Hello:
I am getting the 416 Range Not Satisfiable error back on my browser. however my API is returning just fine and no errors exceptions are being caught as the bytes in my request header are definitely within the target files byte size.
I think it might be easier explaining if I walk through what happens when I try to stream a 5 second long video. It only takes 2 partial requests to get the full video but it fails on the 2nd request. So I am able to play the first 3 seconds of the video.
Here are my request/responses: https://pastebin.com/Bp9ucuMe
- Note that the last response does not trigger an exception or error on my API. The line in my API that returns an empty result is never hit.
Here is my endpoint : https://pastebin.com/2ipWTUU6
What is strange to me is that the 2nd failing response shows
Content-Range: bytes */1085424
but when I inspect that Header I am manually adding to the Response Header content-range on the request that fails it correctly states the start and end bytes my frontend requested. I should state that the start and end are within the total byte size of the file too (total file byte size is 2232304)
I was hoping someone with more experience handling streaming has dealt with something like this and could help me out. If I have any blanks in information let me know and i can fill in.Pastebin
Request 1 : :`GET /path/to/endpoint?filename=%5C%5PATH%5C%5Cto%...
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
Pastebin
[HttpGet("mystreamvideoendpoint")] public IActionResult StreamVi...
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
6 Replies
did aspnet debug logs tell anything about this behavior returning http 416?
@network problem Hey sorry for the late reply, I mustve had this server muted. I ended up making a middleware that logs the request and verified somewhere in my pipeline the response changes to 416 and the header content range changes to the
Content-Range=bytes */135152
.
Its interesting because when I go line by line in the controller it works perfectly, grabs the perfect amount of content/bytes, sets the content range to the right values and so on... This is a simpler API and doesnt have any custom middleware I put on so I am wondering why is it getting screwed up before sending back to the client?i don't know i've never had this issue
there are some parts that could be improved
for example
this can read more than necessary if length set in the request's range is not divisible by buffer.Length
also i guess it's inefficient to open the file in the controller since it's being streamed, it could be left open for a while (is there a session?)
and logs too could be better, and there could be async
but i have no idea if all of this could afflict the issue
It got deeper, so I started hitting the request with postman with hard coded byte request ranges. I could successfully get the video as long as my requested bytes was 0. I could set the end byte request to anything within the file size and I get it.
However, when I set the start byte to 1 I DO get a 206 partial content success, but I cannot stream the video. The video player seems to just be stuck.
Heres where it gets weird, if I make the start byte HALF of the total file size I get a 416 error response.
So my findings so far are:
1. I can partially download just fine if the byte start is 0
2. Despite the controller logic working fine, when the start byte is larger than HALF the video file size, it returns a 416 error and changes the content-range with a wrong byte size (
example: Content-Range=bytes */135152
)
Could this have to do with .mp4 metadata or something?
I tried with an .avi video file type and got the same resultsCould this have to do with .mp4 metadata or something?from what i remember you are not parsing the file, so no
this has been resolved. I was returning File and then later was returning a FileStreamResult and these must have trouble handling partial ranges. Since there was absolutely no changes from my endpoint to my middleware I just took out the FileStreamResult and instead wrote to the response body/headers directly and returned a new EmptyResult().
Im shocked it worked. I am led to believe File or FileStreamResult screws up when handling partial ranges.... I am too inexperienced with partial downloading and streaming to have any other insight lol