2017-10-04 70 views
0

我有一个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女,Int64的偏移,Int64的长度) 在System.Web.Hosting.IIS7WorkerRequest.SendResponseFromFile(字符串名称,Int64的偏移量,Int64的长度) 在System.Web.HttpFileResponseElement。 System.Web.IHttpResponseElement.Send(的HttpWorkerRequest WR) 在System.Web.HttpWriter.Send(的HttpWorkerRequest WR) 在System.Web.HttpResponse.UpdateNativeResponse(布尔sendHeaders) 在System.Web.HttpRuntime.FinishRequestNotification(IIS7WorkerRequest WR, HttpContext上下文,RequestNotificationStatus &状态)

我已经更新了代码给我们E中的文件流而不是一个流读取器,像这样:

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

正如我已经看到了这个建议一气呵成不打开整个文件,但它并没有区别。

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

+0

我不是IIS专家,但我知道您的网站可用的内存并不像服务器中有多少内存那么容易。而1.5 GB并不是那么重要。你知道它需要多少并发请求来反馈吗?有多少其他网站正在运行?安装类似蚂蚁事件探查器可能会帮助您找出解决方案。 – Crowcoder

回答

1

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

+0

这不是范围下载已经做了什么?我可能完全错了?! – Bex

+0

@Bex,那不是我读的。我将开始和结束值解释为从视频请求的范围(如字节数组)。不是将文件分块的方法。但我当然也可能错了她。 – Hintham