2017-10-04 72 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