如何在ASP.Net MVC 中实现视频文件流?
How to implement video file streaming in ASP.Net MVC?
我想实现简单的视频文件流。
这是我的 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 Internal Server Error?如何正确处理我的文件流?
AFAIK,您在不处理文件流的情况下下载内容的实现是正确的。
因为您一直在使用 HttpResponseMessage
返回响应,该响应在完成向客户端发送响应后由框架本身自动处理。
这已经被MSFT guy in comment of 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
的对象设置在 Content
属性 HttpResponseMessage
.
按以下方式处理 ByteRangeStreamContent 对象:
protected override void Dispose(bool disposing)
{
Contract.Assert(_byteRangeContent != null);
if (disposing)
{
if (!_disposed)
{
_byteRangeContent.Dispose();
_content.Dispose();
_disposed = true;
}
}
base.Dispose(disposing);
}
在ByteRangeStreamContent
的上述Dispose
方法中,你可以看到它正在处理自身并处理_content
(在你的情况下FileStream
)也是用于创建 ByteRangeStreamContent
对象的流。
我坚信,您没有处理文件流的实现是正确的,因为在完成向客户端发送响应后处理会按顺序开始。
我想实现简单的视频文件流。 这是我的 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 Internal Server Error?如何正确处理我的文件流?
AFAIK,您在不处理文件流的情况下下载内容的实现是正确的。
因为您一直在使用 HttpResponseMessage
返回响应,该响应在完成向客户端发送响应后由框架本身自动处理。
这已经被MSFT guy in comment of 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
的对象设置在 Content
属性 HttpResponseMessage
.
按以下方式处理 ByteRangeStreamContent 对象:
protected override void Dispose(bool disposing)
{
Contract.Assert(_byteRangeContent != null);
if (disposing)
{
if (!_disposed)
{
_byteRangeContent.Dispose();
_content.Dispose();
_disposed = true;
}
}
base.Dispose(disposing);
}
在ByteRangeStreamContent
的上述Dispose
方法中,你可以看到它正在处理自身并处理_content
(在你的情况下FileStream
)也是用于创建 ByteRangeStreamContent
对象的流。
我坚信,您没有处理文件流的实现是正确的,因为在完成向客户端发送响应后处理会按顺序开始。