简体   繁体   中英

How to implement video file streaming in ASP.Net MVC?

I want to implement simple video file streaming. There is my API controller:

[HttpGet]
[Route("api/VideoContent")]
public HttpResponseMessage GetVideoContent([FromUri] string fileName)
{
    if (fileName == null)
    {
        return new HttpResponseMessage(HttpStatusCode.BadRequest);
    }

    if (Request.Headers.Range != null)
    {
        try
        {
            //using (FileStream fileStream = _videoFileProvider.GetFileStream(fileName))
            //{
                HttpResponseMessage partialResponse = Request.CreateResponse(HttpStatusCode.PartialContent);
                FileStream fileStream = _videoFileProvider.GetFileStream(fileName);
                partialResponse.Content = new ByteRangeStreamContent(fileStream, Request.Headers.Range, new MediaTypeHeaderValue("video/mp4"));
                return partialResponse;
            //}

        }
        catch (Exception)
        {
            return new HttpResponseMessage(HttpStatusCode.InternalServerError);
        }
    }

    return new HttpResponseMessage(HttpStatusCode.RequestedRangeNotSatisfiable);
}

This code is working, but as you see fileStream not disposed. I tried to use using block (commented lines), but this code doesn't work - in debug mode method run without exceptions, but browser shows response with 500 error code.

Where is my mistake? Why I am getting 500 Internal Server Error? How to correctly dispose file stream in my case?

AFAIK, what have you implemented for downloading content without disposing filestream is right.

As you have been using HttpResponseMessage for returning response which is automatically disposed by the framework itself after done with sending response to the client.

This has already been pointed by MSFT guy in comment of another post

If you looks at dispose method of HttpResponseMessage in source code ,

        protected virtual void Dispose(bool disposing)
        {
            // The reason for this type to implement IDisposable is 
            //that it contains instances of types that implement
            // IDisposable (content). 
            if (disposing && !_disposed)
            {
                _disposed = true;
                if (_content != null)
                {
                    _content.Dispose();
                }
            }
        }

You can see _ content has been disposed which is of type HttpContent ie in your case, object of ByteRangeStreamContent set in the Content property of HttpResponseMessage .

Disposing ByteRangeStreamContent object implemented in following way :

        protected override void Dispose(bool disposing)
        {
            Contract.Assert(_byteRangeContent != null);
            if (disposing)
            {
                if (!_disposed)
                {
                    _byteRangeContent.Dispose();
                    _content.Dispose();
                    _disposed = true;
                }
            }
            base.Dispose(disposing);
        }

In above Dispose method of ByteRangeStreamContent , you can see that it is disposing itself and disposing _ content (in your case FileStream ) as well which is stream used for creating ByteRangeStreamContent object.

I strongly believe, your implementation without disposing filestream is correct as disposing starts in sequence when done with sending response to client.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM