ASP.Net Core Web Api 中的异步视频流无法正常工作
Async video streaming in ASP.Net Core Web Api is not working
我以前使用过 http://www.strathweb.com/2013/01/asynchronously-streaming-video-with-asp-net-web-api/ 这种技术并且非常适合异步视频流。
但对于 ASP.NET 核心,这种方式无法按预期工作。
通过视频流 class 是:
public class VideoStream
{
private readonly string _filename;
public VideoStream(string filename)
{
_filename = filename;
}
public async Task WriteToStream(Stream outputStream, HttpContent content, TransportContext context)
{
try
{
var buffer = new byte[65536];
using (var video = File.Open(_filename, FileMode.Open, FileAccess.Read))
{
var length = (int)video.Length;
var bytesRead = 1;
while (length > 0 && bytesRead > 0)
{
bytesRead = video.Read(buffer, 0, Math.Min(length, buffer.Length));
await outputStream.WriteAsync(buffer, 0, bytesRead);
length -= bytesRead;
}
}
}
catch (Exception)
{ return; }
finally
{
outputStream.Flush();
outputStream.Dispose();
}
}
}
并且我对视频流请求执行了以下操作:
[HttpGet]
[Route("[action]")]
public IActionResult GetVideo(int id)
{
var fileName = GetVideoFileName(id);
var video = new VideoStream(fileName);
var response = new HttpResponseMessage
{
Content = new PushStreamContent(video.WriteToStream, new MediaTypeHeaderValue("video/mp4"))
};
var objectResult = new ObjectResult(response);
objectResult.ContentTypes.Add(new Microsoft.Net.Http.Headers.MediaTypeHeaderValue("video/mp4"));
return objectResult;
}
因为默认情况下 Asp.Net Core 没有用于 video/mp4 的内置媒体格式化程序,我创建了以下自定义媒体格式化程序
public class VideoOutputFormatter : IOutputFormatter
{
public bool CanWriteResult(OutputFormatterCanWriteContext context)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
return true;
}
public async Task WriteAsync(OutputFormatterWriteContext context)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
var response = context.HttpContext.Response;
response.ContentType = "video/mp4";
How to impelemnt ???
}
}
并将以下行添加到 Startup.cs
services.AddMvc(options =>
{
options.OutputFormatters.Add(new VideoOutputFormatter());
});
它实际上调用了我的自定义格式化程序。
我不知道如何为 video/mp4 实现这个自定义媒体格式化程序。
谁能帮帮我?
查看 Asp.NET Core 的源代码确实帮助我找到了这个问题的答案。他们有一个 StreamOutputFormatter class 非常接近您想要使用的。我只需要修改它来寻找 PushStreamContent
,它就像一个魅力。
这是我完整的 VideoOutputFormatter:
public class VideoOutputFormatter : IOutputFormatter
{
public bool CanWriteResult(OutputFormatterCanWriteContext context)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
if (context.Object is PushStreamContent)
return true;
return false;
}
public async Task WriteAsync(OutputFormatterWriteContext context)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
using (var stream = ((PushStreamContent)context.Object))
{
var response = context.HttpContext.Response;
if (context.ContentType != null)
{
response.ContentType = context.ContentType.ToString();
}
await stream.CopyToAsync(response.Body);
}
}
}
不是将 HttpResponseMessage
包装在控制器的 ObjectResult
中,您只想将 PushStreamContent
对象推入 ObjectResult
中。您仍然需要在 ObjectResult
上设置 MediaTypeHeaderValue
。
我以前使用过 http://www.strathweb.com/2013/01/asynchronously-streaming-video-with-asp-net-web-api/ 这种技术并且非常适合异步视频流。
但对于 ASP.NET 核心,这种方式无法按预期工作。
通过视频流 class 是:
public class VideoStream
{
private readonly string _filename;
public VideoStream(string filename)
{
_filename = filename;
}
public async Task WriteToStream(Stream outputStream, HttpContent content, TransportContext context)
{
try
{
var buffer = new byte[65536];
using (var video = File.Open(_filename, FileMode.Open, FileAccess.Read))
{
var length = (int)video.Length;
var bytesRead = 1;
while (length > 0 && bytesRead > 0)
{
bytesRead = video.Read(buffer, 0, Math.Min(length, buffer.Length));
await outputStream.WriteAsync(buffer, 0, bytesRead);
length -= bytesRead;
}
}
}
catch (Exception)
{ return; }
finally
{
outputStream.Flush();
outputStream.Dispose();
}
}
}
并且我对视频流请求执行了以下操作:
[HttpGet]
[Route("[action]")]
public IActionResult GetVideo(int id)
{
var fileName = GetVideoFileName(id);
var video = new VideoStream(fileName);
var response = new HttpResponseMessage
{
Content = new PushStreamContent(video.WriteToStream, new MediaTypeHeaderValue("video/mp4"))
};
var objectResult = new ObjectResult(response);
objectResult.ContentTypes.Add(new Microsoft.Net.Http.Headers.MediaTypeHeaderValue("video/mp4"));
return objectResult;
}
因为默认情况下 Asp.Net Core 没有用于 video/mp4 的内置媒体格式化程序,我创建了以下自定义媒体格式化程序
public class VideoOutputFormatter : IOutputFormatter
{
public bool CanWriteResult(OutputFormatterCanWriteContext context)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
return true;
}
public async Task WriteAsync(OutputFormatterWriteContext context)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
var response = context.HttpContext.Response;
response.ContentType = "video/mp4";
How to impelemnt ???
}
}
并将以下行添加到 Startup.cs
services.AddMvc(options =>
{
options.OutputFormatters.Add(new VideoOutputFormatter());
});
它实际上调用了我的自定义格式化程序。 我不知道如何为 video/mp4 实现这个自定义媒体格式化程序。 谁能帮帮我?
查看 Asp.NET Core 的源代码确实帮助我找到了这个问题的答案。他们有一个 StreamOutputFormatter class 非常接近您想要使用的。我只需要修改它来寻找 PushStreamContent
,它就像一个魅力。
这是我完整的 VideoOutputFormatter:
public class VideoOutputFormatter : IOutputFormatter
{
public bool CanWriteResult(OutputFormatterCanWriteContext context)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
if (context.Object is PushStreamContent)
return true;
return false;
}
public async Task WriteAsync(OutputFormatterWriteContext context)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
using (var stream = ((PushStreamContent)context.Object))
{
var response = context.HttpContext.Response;
if (context.ContentType != null)
{
response.ContentType = context.ContentType.ToString();
}
await stream.CopyToAsync(response.Body);
}
}
}
不是将 HttpResponseMessage
包装在控制器的 ObjectResult
中,您只想将 PushStreamContent
对象推入 ObjectResult
中。您仍然需要在 ObjectResult
上设置 MediaTypeHeaderValue
。