Stream.WriteAsync抛出了“远程主机关闭了连接”异常。

6
我有一个asp.net webforms应用程序,需要从以varbinary格式保存在数据库中的视频中检索并将其显示为html5视频标记。
通过Google搜索,我找到了一种使用ASP.Net WebApi异步播放的方法,它可以正常工作。
第一个问题:
当视频第一次播放时,用户单击播放按钮重新播放视频时,会在await outputStream.WriteAsync(buffer, 0, bytesRead)行抛出The remote host closed the connection. The error code is 0x800704CD异常。
第二个问题:
当用户单击寻求栏时,视频将从头开始播放。
注意:
Internet Explorer 11可以播放视频而没有任何问题,但Firefox和Chrome都有这些问题。
我该如何解决这个问题?
以下是我的代码:
public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.EnableCors();

        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "VideoApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

public class VideoController : ApiController
{
    public IVideoRepository videoRepository;

    public HttpResponseMessage Get(long id)
    {
        try
        {
            videoRepository = new VideoRepository();
            Video video = videoRepository.load(id);

            if (video != null)
            {
                var videoStream = new VideoStream(video.fileContent);
                string ext = video.extension;

                var response = Request.CreateResponse();

                response.Content = new PushStreamContent((Action<Stream, HttpContent, TransportContext>)videoStream.WriteToStream, new MediaTypeHeaderValue("video/" + ext));

                response.Content.Headers.Add("Content-Disposition", "attachment;filename=" + video.fullName.Replace(" ", ""));
                response.Content.Headers.Add("Content-Length", videoStream.FileLength.ToString());

                return response;
            }
            else
            {
                return Request.CreateResponse(HttpStatusCode.NotFound);
            }
        }
        catch (Exception e)
        {
            return Request.CreateErrorResponse(HttpStatusCode.ServiceUnavailable, e);
        }
    }
}

public class VideoStream
{
    private readonly byte[] _fileContent;
    private long _contentLength;

    public long FileLength
    {
        get { return _contentLength; }
    }

    public VideoStream(byte[] content)
    {
        _contentLength = content.Length;
        _fileContent = content;
    }

    public async void WriteToStream(Stream outputStream, HttpContent content, TransportContext context)
    {
        try
        {
            var buffer = new byte[65536];

            MemoryStream memoryStream = new MemoryStream();
            memoryStream.Write(_fileContent, 0, _fileContent.Length);
            memoryStream.Position = 0;
            using (memoryStream)
            {
                var length = (int)memoryStream.Length;
                var bytesRead = 1;

                while (length > 0 && bytesRead > 0)
                {
                    bytesRead = memoryStream.Read(buffer, 0, Math.Min(length, buffer.Length));
                    await outputStream.WriteAsync(buffer, 0, bytesRead);
                    length -= bytesRead;
                }
            }
        }
        catch (Exception e)
        {
            throw e;
        }
        finally
        {
            outputStream.Close();
        }
    }
}

更新

在尝试了这种方法后,我不得不使用这种方式,但是新的方式存在一个寻找栏问题,在Chrome和FireFox中,当用户点击寻找栏来寻找时间时它无法正常工作。

2个回答

0

ASP.NET 对于视频流传输并不是很擅长。第三方视频流传输解决方案是最好的选择。

有一些视频流服务器(例如Wowza),但它们需要安装并且你必须购买许可证。

云端流媒体服务是另一个选择。我个人更喜欢AWS Cloudfront。他们提供各种全球分布式内容交付区域的分发,成本非常便宜,并且你可以确保它能够处理任何流量数量(即使所有用户同时观看同一视频)。


0
你可能已经得到了答案。但这可能会帮助其他人- 我最好的选择是从响应头中删除Content-lengthContent-Length告诉调用者它需要在响应中接收这个固定长度。 当你点击播放按钮时,不会接收完整的视频流(即没有接收到整个Content-Length)。因此出现错误。 另一种方法是使用response.Headers.TransferEncodingChunked = true,它告诉调用者将以块的形式接收响应。唯一的问题是,即使流不存在,你也会得到一个200OK。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接