Asp.net

ASP.Net Core Web Api 中的非同步影片流不起作用

  • November 18, 2020

我以前使用過http://www.strathweb.com/2013/01/asynchronously-streaming-video-with-asp-net-web-api/這種技術,並且非常適合非同步影片流。

但對於 ASP.NET Core,這種方式無法按預期工作。

按影片流類是:

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 沒有用於影片/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());
       });

它實際上呼叫了我的自定義格式化程序。我不知道如何為影片/mp4 實現這個自定義媒體格式化程序。任何人都可以幫助我嗎?

查看 Asp.NET Core 的原始碼確實幫助我找到了這個問題的答案。他們有一個非常接近您想要使用的StreamOutputFormatter類。我只需要修改它來尋找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);
       }
   }
}

與其將 in 包裝HttpResponseMessageObjectResult控制器中,不如將PushStreamContent對象推入in 中ObjectResult。您仍然需要MediaTypeHeaderValueObjectResult.

引用自:https://stackoverflow.com/questions/41698435