【问题标题】:HTML5 video - ashx handler - seekHTML5 视频 - ashx 处理程序 - 寻找
【发布时间】:2014-06-23 20:44:51
【问题描述】:

我正在尝试使用 ashx 处理程序作为 HTML5 视频源。我可以做到这一点,但我无法在已经缓冲的视频上进一步前进。

我可以在使用标准 MP4 源的网络选项卡上看到,向前搜索会创建另一个请求,但使用处理程序不会。

部分视频超过 1 GB。

到目前为止,我必须这样做才能使视频正常工作:

public void ProcessRequest(HttpContext context)
{
    context.Response.Buffer = false;
    context.Response.ContentType = "video/mp4";
    FileInfo file = new FileInfo(path);
    int len = (int)file.Length, bytes;
    context.Response.AppendHeader("content-length", len.ToString());
    byte[] buffer = new byte[1024];
    Stream outStream = context.Response.OutputStream;
    using (Stream stream = File.OpenRead(path))
    {
        while (len > 0 && (bytes = stream.Read(buffer, 0, buffer.Length)) > 0)
        {
            outStream.Write(buffer, 0, bytes);
            len -= bytes;
        }
    }
}

取自 Marck Gravells 的帖子Best way to stream files in ASP.NET

<video id="video-player" class="video-js vjs-default-skin" controls
     preload="auto" poster="MY_VIDEO_POSTER.jpg"
     data-setup="{}">
     <source src="/Handlers/VideoHandler.ashx" type='video/mp4'>
     <p class="vjs-no-js">
        To view this video please enable JavaScript, and consider upgrading to a web browser that
        <a href="http://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
     </p>
    </video>

使用 video.js,但如果我直接在浏览器中调用处理程序,也会发生同样的情况。

我该如何解决这个问题?我很可能错过了一些简单的东西。

更新

进一步查看后,我现在知道我需要“Accept-Ranges”。

我现在有

context.Response.ContentType = "video/mp4";

var request = HttpContext.Current.Request;
FileInfo file = new FileInfo(filePath);
var responseLength = (int)file.Length;
var buffer = new byte[1024];
var startIndex = 0;

if (request.Headers["Range"] != null)
{
    var match = Regex.Match(request.Headers["Range"], @"bytes=(\d*)-(\d*)");
    startIndex = Parse<int>(match.Groups[1].Value);
    responseLength = (Parse<int?>(match.Groups[2].Value) + 1 ?? responseLength) - startIndex;
    context.Response.StatusCode = (int)HttpStatusCode.PartialContent;
    context.Response.Headers["Content-Range"] = "bytes " + startIndex + "-" + (startIndex + responseLength - 1) + "/" + responseLength;
}

context.Response.Headers["Accept-Ranges"] = "bytes";
context.Response.Headers["Content-Length"] = responseLength.ToString();
context.Response.Cache.SetCacheability(HttpCacheability.Public);

context.Response.Buffer = false;

Supporting resumable HTTP-downloads through an ASHX handler? 的帮助下,但现在写给我的错误是问题

HttpException 未被用户代码处理 远程主机关闭了连接。错误代码为0x800704CD。

我试过了:

using (Stream stream = File.OpenRead(filePath))
{

    stream.Seek(startIndex, SeekOrigin.Begin);
    while ((responseLength - startIndex) > 0 && (bytes = stream.Read(buffer, 0, buffer.Length)) > 0)
    {
        response.OutputStream.Write(buffer, 0, bytes);
        responseLength -= bytes;
    }
}

using (Stream stream = File.OpenRead(filePath))
{
    stream.Seek(startIndex, SeekOrigin.Begin);
    int bufferLength = buffer.Length, bytesRead;
    while (responseLength > bufferLength && (bytesRead = stream.Read(buffer, 0, bufferLength)) > 0)
    {
        response.OutputStream.Write(buffer, 0, bytesRead);
        responseLength -= bytesRead;
    }
    while (responseLength > 0 && (bytesRead = stream.Read(buffer, 0, responseLength)) > 0)
    {
        response.OutputStream.Write(buffer, 0, bytesRead);
        responseLength -= bytesRead;
    }
}

我该如何解决这个问题?

【问题讨论】:

    标签: html video video-streaming html5-video ashx


    【解决方案1】:

    最后一个错误是 Chrome 造成的。

    以下在 Firefox 中运行良好。

    如果有人知道 Chrome 为何取消连接,请分享。

        public void ProcessRequest(HttpContext context)
        {
            context.Response.AddHeader("content-disposition", "filename=" + Path.GetFileName(filePath));
            context.Response.ContentType = "video/mp4";
    
            var request = HttpContext.Current.Request;
            FileInfo file = new FileInfo(filePath);
            var responseLength = (int)file.Length;
            var buffer = new byte[512];
            var startIndex = 0;
    
            if (request.Headers["Range"] != null )
            {
                var match = Regex.Match(request.Headers["Range"], @"bytes=(\d*)-(\d*)");
                startIndex = Parse<int>(match.Groups[1].Value);
                responseLength = (Parse<int?>(match.Groups[2].Value) + 1 ?? responseLength) - startIndex;
                context.Response.StatusCode = (int)HttpStatusCode.PartialContent;
                context.Response.Headers["Content-Range"] = "bytes " + startIndex + "-" + (startIndex + responseLength - 1) + "/" + responseLength;
            }
    
            context.Response.Headers["Accept-Ranges"] = "bytes";
            context.Response.Headers["Content-Length"] = responseLength.ToString();
            context.Response.Cache.SetCacheability(HttpCacheability.Public);
    
            context.Response.BufferOutput = false;
            FileStream fileStram = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            using (fileStram)
            {
                fileStram.Seek(startIndex, SeekOrigin.Begin);
                int bytesRead = fileStram.Read(buffer, 0, buffer.Length);
                while (bytesRead > 0)
                {
                    context.Response.OutputStream.Write(buffer, 0, bytesRead);
                    bytesRead = fileStram.Read(buffer, 0, buffer.Length);
                }
            }
        }
    
        public static T Parse<T>(object value)
        {
            // Convert value to string to allow conversion from types like float to int
            // converter.IsValid only works since .NET4 but still returns invalid values for a few cases like NULL for Unit and not respecting locale for date validation
            try { return (T)System.ComponentModel.TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(value.ToString()); }
            catch (Exception) { return default(T); }
        }
    

    【讨论】:

    • 不知道为什么,但这似乎是禁用缓冲的结果。但是,如果您修复 Content-Range 标头中的错误,它应该 "/" + file.Length 而不是 "/" + responseLength 因为在中途恢复下载时它的值不同,那么即使禁用缓冲导致错误,它也会在 Chrome 中工作。如果你想让它在 IE 中工作,你需要添加 ETAG。
    【解决方案2】:

    无需打开和读取文件。我通过添加"Accept-Ranges" 标题并通过context.Response.TransmitFile 翻译文件来遵循这个技巧。 现在视频正在每个浏览器(例如 Chrome、Firefox)上播放和搜索

     if (fi.Extension == ".mp4")
     {
        //Reset and set response headers. The Accept-Ranges Bytes header is important to allow resuming videos.
        context.Response.AddHeader("Accept-Ranges", "bytes");
     }
     docRepo.AddDocumentView(FileDetail.ID);
     context.Response.TransmitFile(HttpContext.Current.Server.MapPath(General.PathConstants.Documents + Id + fi.Extension));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-07
      • 1970-01-01
      • 2012-05-14
      • 2012-11-26
      • 2011-07-31
      • 1970-01-01
      • 2012-05-21
      相关资源
      最近更新 更多