视频范围下载 - 内存不足异常

时间:2017-10-04 10:26:55

标签: c# asp.net video-streaming ashx

我有一个http hander(ashx),用于发送要在网站上播放的视频。

视频文件大小可以是20MB到200MB之间的任何值,但最近我在播放一些较大的视频时收到内存不足的异常。 服务器有足够的磁盘空间,通常有1.5GB的RAM可用。 我在本地运行时没有收到错误,所以尽管服务器上有足够的内存但显然存在问题。

我不确定代码是否效率低下,但由于这是一个继承的项目,我不确定它是如何工作的,或者是否有更好的方法。

我使用的代码如下:

  private void RangeDownload(string fullpath, HttpContext context)
    {
        long size, start, end, length, fp = 0;
        using (StreamReader reader = new StreamReader(fullpath))
        {

            size = reader.BaseStream.Length;
            start = 0;
            end = size - 1;
            length = size;

            context.Response.AddHeader("Accept-Ranges", "0-" + size);

            if (!String.IsNullOrEmpty(context.Request.ServerVariables["HTTP_RANGE"]))
            {
                long anotherStart = start;
                long anotherEnd = end;
                string[] arr_split = context.Request.ServerVariables["HTTP_RANGE"].Split(new char[] { Convert.ToChar("=") });
                string range = arr_split[1];

                if (range.IndexOf(",") > -1)
                {
                    context.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size);
                    throw new HttpException(416, "Requested Range Not Satisfiable");

                }

                if (range.StartsWith("-"))
                {
                    anotherStart = size - Convert.ToInt64(range.Substring(1));
                }
                else
                {
                    arr_split = range.Split(new char[] { Convert.ToChar("-") });
                    anotherStart = Convert.ToInt64(arr_split[0]);
                    long temp = 0;
                    anotherEnd = (arr_split.Length > 1 && Int64.TryParse(arr_split[1].ToString(), out temp)) ? Convert.ToInt64(arr_split[1]) : size;
                }
                anotherEnd = (anotherEnd > end) ? end : anotherEnd;
                if (anotherStart > anotherEnd || anotherStart > size - 1 || anotherEnd >= size)
                {

                    context.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size);
                    throw new HttpException(416, "Requested Range Not Satisfiable");
                }
                start = anotherStart;
                end = anotherEnd;

                length = end - start + 1;
                fp = reader.BaseStream.Seek(start, SeekOrigin.Begin);
                context.Response.StatusCode = 206;
            }
        }
        context.Response.AddHeader("Content-Type", "video/mp4");    
        context.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size);
        context.Response.AddHeader("Content-Length", length.ToString());
        context.Response.WriteFile(fullpath, fp, length);
        context.Response.End();

    }

我得到的例外是:

  

异常类型:OutOfMemoryException       异常消息:类型的异常' System.OutOfMemoryException'被扔了。      在System.Web.Hosting.IIS7WorkerRequest.SendResponseFromFileStream(FileStream f,Int64 offset,Int64 length)      在System.Web.Hosting.IIS7WorkerRequest.SendResponseFromFile(String name,Int64 offset,Int64 length)      在System.Web.HttpFileResponseElement.System.Web.IHttpResponseElement.Send(HttpWorkerRequest wr)      在System.Web.HttpWriter.Send(HttpWorkerRequest wr)      在System.Web.HttpResponse.UpdateNativeResponse(Boolean sendHeaders)      在System.Web.HttpRuntime.FinishRequestNotification(IIS7WorkerRequest wr,HttpContext context,RequestNotificationStatus& status)

我更新了代码以使用文件流而不是像这样的流阅读器:

   using (var reader = new FileStream(fullpath,System.IO.FileMode.Open,
            System.IO.FileAccess.Read, System.IO.FileShare.Read))

正如我所看到的那样,它表明这不会一次性打开整个文件,但没有任何区别。

这是服务器空间问题还是编码问题?

1 个答案:

答案 0 :(得分:1)

根据MSDN您使用的WriteFile(String, Int64, Int64)重载可能会抛出大文件的异常。有一篇KB文章引用了代码示例,该文章展示了如何解决该问题。它基本上归结为将文件拆分为较小的块并在每个块之后刷新输出流。