我制作了一个音频流处理程序。它在 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);
}
}