【问题标题】:asp.net System.OutOfMemory Exceptionasp.net System.OutOfMemory 异常
【发布时间】:2018-04-11 08:49:11
【问题描述】:

我正在使用文件表将视频文件存储在我的 sql 服务器中,并且我想在网络浏览器中观看它们。一个 aspx Web 服务器正在处理该请求。 VideoHandler.ashx 处理程序类用于处理请求并将数据发送到浏览器。这是流式传输视频文件的代码:

            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];

                    // Make sure the client hasn't sent us a multibyte range
                    if (range.IndexOf(",") > -1)
                    {
                        context.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size);
                        throw new HttpException(416, "Requested Range Not Satisfiable");
                    }

                    // If the range starts with an '-' we start from the beginning
                    // If not, we forward the file pointer
                    // And make sure to get the end byte if spesified
                    if (range.StartsWith("-"))
                    {
                        // The n-number of the last bytes is requested
                        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;
                    }

                    // End bytes can not be larger than $end.
                    anotherEnd = (anotherEnd > end) ? end : anotherEnd;
                    // Validate the requested range and return an error if it's not correct.
                    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; // Calculate new content length
                    fp = reader.BaseStream.Seek(start, SeekOrigin.Begin);
                    context.Response.StatusCode = 206;
                    reader.Dispose();
                    reader.Close();
                }
            }
            // Notify the client the byte range we'll be outputting
            context.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size);
            context.Response.AddHeader("Content-Length", length.ToString());
            // Start buffered download
            context.Response.WriteFile(fullpath, fp, length);
            context.Response.End();
        }

只要视频文件不太大,代码就可以正常工作。例如,当流式传输大小为 72MB 的视频时,一切正常。当我想流式传输大小为 612MB 的视频时,会出现此问题。然后应用程序抛出异常:

"System.OutOfMemoryException"
Operation: GET/VideoHandler.ashx

这是堆栈跟踪:

System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
    at  System.Web.Hosting.IIS7WorkerRequest.SendResponseFromFileStream (System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
    at  System.Web.Hosting.IIS7WorkerRequest.SendResponseFromFile (System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
    at  System.Web.HttpFileResponseElement.System.Web.IHttpResponseElement.Send (System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
    at  System.Web.HttpWriter.Send (System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
    at  System.Web.HttpResponse.UpdateNativeResponse (System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)
    at  System.Web.HttpRuntime.FinishRequestNotification (System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a)

不幸的是我无法弄清楚问题出在哪里以及导致异常的原因......我在观看诊断工具时观察到的是,当请求到来时,进程内存并没有增加但是抛出了异常。 此外,服务器/应用程序没有崩溃。

【问题讨论】:

  • 它是否在确切的行上崩溃?您是否尝试过手动将流分块写入响应?因为你已经打开了一个文件句柄,所以你不必打开文件两次。也许 WriteFile 在写入之前先尝试读取整个文件?
  • 它不会在特定点崩溃。当我从第一行开始调试代码时,它一直运行到最后,没有任何错误。但在第二次错误立即发生。
  • 也许这可以说明一些问题:support.microsoft.com/en-us/help/812406/… 他们在 VB 中提供了一个示例,翻译起来应该很简单
  • 非常感谢您提供的链接。这对我理解问题所在有很大帮助:)

标签: c# asp.net .net sql-server out-of-memory


【解决方案1】:

由于 Clontea 先生的链接,我能够找到一个现在有效的解决方案。我所要做的就是将 StreamReader 更改为 FileStream。使用此代码,您可以在浏览器中流式传输视频并进行搜索。

        long size, start, end, length, fp = 0;
        byte[] buffer = new byte[10000];
        int ilength = 0;

        using (Stream reader = new FileStream(fullpath, FileMode.Open, FileAccess.Read, FileShare.Read))
        {
            size = reader.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];

                // Make sure the client hasn't sent us a multibyte range
                if (range.IndexOf(",") > -1)
                {
                    context.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size);
                    throw new HttpException(416, "Requested Range Not Satisfiable");
                }

                // If the range starts with an '-' we start from the beginning
                // If not, we forward the file pointer
                // And make sure to get the end byte if spesified
                if (range.StartsWith("-"))
                {
                    // The n-number of the last bytes is requested
                    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;
                }

                // End bytes can not be larger than $end.
                anotherEnd = (anotherEnd > end) ? end : anotherEnd;
                // Validate the requested range and return an error if it's not correct.
                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; // Calculate new content length
                fp = reader.Seek(start, SeekOrigin.Begin);
                context.Response.StatusCode = 206;

                ilength = reader.Read(buffer, 0, 10000);
                reader.Dispose();
                reader.Close();
            }
        }
        // Notify the client the byte range we'll be outputting
        context.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size);
        context.Response.AddHeader("Content-Length", length.ToString());
        // Start buffered download
        context.Response.OutputStream.Write(buffer, 0, ilength);
        HttpContext.Current.ApplicationInstance.CompleteRequest();
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-21
    • 1970-01-01
    • 2015-06-21
    • 1970-01-01
    • 1970-01-01
    • 2016-09-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多