3

オーディオ ストリーミング ハンドラを作成しました。64 ビットの Windows マシンで正常に動作します。

32 ビット マシンで IE とフィドラーを使用している場合、一部のオーディオの再生後にオーディオが停止し、オーディオ タグによってエラー MEDIA_ERR_DECODE が生成されます。

ストリーミング コードは次のとおりです。

public void ProcessRequest(HttpContext context)  
 {  
    try  
    {  
       //context.Response.Headers.Clear();
       string strBrowser = context.Request.Browser.Browser.ToUpper();
       string strFileName = Path.GetFileNameWithoutExtension(context.Request.FilePath);
       string mimetype;  
       MemoryStream audioStream = null;  
       if (strFileName != null && strFileName.Length > 0)  
       {  
            switch (strBrowser)
            {
                case "FIREFOX":
                    mimetype = "audio/ogg";
                    break;
                default:
                    mimetype = "audio/mpeg";
                    break;
            }

         Dictionary<string, StreamDetails> mapStreamDetails =  
                (Dictionary<string,StreamDetails>)context.Application["StreamDetails"];
         StreamDetails streamDetails = null;

         if (mapStreamDetails.ContainsKey(strFileName))
         {
           streamDetails = mapStreamDetails[strFileName];
         }

         if (streamDetails != null && streamDetails.AudioStream !=null)                
         {
           audioStream = streamDetails.AudioStream;
           context.Response.ContentType = mimetype;
           if (!String.IsNullOrEmpty(context.Request.ServerVariables["HTTP_RANGE"]))
            {
               //request for chunk
               RangeDownload(audioStream, context);
            }
           else
            {
              //ask for all 
              long fileLength = audioStream.Length;//File.OpenRead(fullpath).Length;
              context.Response.AddHeader("Content-Length", fileLength.ToString());
              byte[] responseBytes = new byte[(int)audioStream.Length];
              audioStream.Read(responseBytes, 0, (int)audioStream.Length);
              context.Response.BinaryWrite(responseBytes);
             }
         }
         else
         {
           throw new HttpException(404, "audio stream not found : " + strFileName);
         }
       }
       else
       {
         context.Response.Write("Invalid request");                
       }
    }
    catch (Exception ex)
    {            
        Common.DebugWriteLine("Exception occured" + ex.Message + ex.StackTrace);
    }
}

 private void RangeDownload(MemoryStream audioStream, HttpContext context)
 {
    long size, start, end, length, fp = 0;
    byte[] responseBytes = null;        
    size = audioStream.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)
       {
         // (?) Shoud this be issued here, or should the first
         // range be used? Or should the header be ignored and
         // we output the whole content?
         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 = audioStream.Seek(start, SeekOrigin.Begin);
        context.Response.StatusCode = 206;            

        responseBytes = new byte[(int)length];
        audioStream.Read(responseBytes, (int)0, (int)length);
    }        
    // 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());
    try
    {
      if (responseBytes != null)
      {
        context.Response.BinaryWrite(responseBytes);
      }                    
    }
    catch (Exception ex)
    {
      Common.DebugWriteLine("Exception occured in streaming data : " + ex.Message + 
                                                           "Trace : " + ex.StackTrace);
    }
}
4

0 に答える 0