如何在 ASP.Net MVC 中实现视频文件流式传输?

Posted

技术标签:

【中文标题】如何在 ASP.Net MVC 中实现视频文件流式传输?【英文标题】:How to implement video file streaming in ASP.Net MVC? 【发布时间】:2017-07-07 14:06:51 【问题描述】:

我想实现简单的视频文件流。 有我的 API 控制器:

[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);

此代码正在运行,但如您所见,fileStream 未处理。我尝试使用 using 块(注释行),但此代码不起作用 - 在调试模式下方法运行无异常,但浏览器显示 500 错误代码的响应。

我的错误在哪里?为什么我收到 500 内部服务器错误?在我的情况下如何正确处理文件流?

【问题讨论】:

Maxad has a good answer 通过 finally 块关闭流。 【参考方案1】:

AFAIK,你在不处理文件流的情况下下载内容是正确的。

正如您一直在使用HttpResponseMessage 来返回响应,该响应在完成向客户端发送响应后由框架本身自动处理。

这已经被MSFT guy 在comment 的another post 中指出

如果你看HttpResponseMessage in source code的dispose方法,

        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();
                
            
        

您可以看到 _content 已被处置,其类型为 HttpContent,即在您的情况下,ByteRangeStreamContent 的对象设置在 HttpResponseMessageContent 属性中。

处理ByteRangeStreamContent对象的实现方式如下:

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

在上面ByteRangeStreamContentDispose 方法中,您可以看到它正在处理自己并处理_content(在您的情况下为FileStream)以及用于创建ByteRangeStreamContent 对象的流。

我坚信,您在不处理文件流的情况下的实现是正确的,因为在完成向客户端发送响应后,处理是按顺序开始的。

【讨论】:

以上是关于如何在 ASP.Net MVC 中实现视频文件流式传输?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ASP.NET MVC 5 中实现自定义身份验证

您将如何在 asp.net mvc 中实现面包屑助手?

如何在 ASP.NET MVC 中实现自定义主体和身份?

如何使用 ASP.NET MVC 在 Kendo UI Grid 中实现 N 级嵌套层次结构

在 ASP.NET MVC 中实现“记住我”功能

如何在ASP.NET MVC中实现报表打印和导出