我尝试将音频文件流式传输到Angular应用程序,其中html5音频元素和src设置为我的api终点(例如./audio/234)。我的后端是用.NET Core 2.0实现的。我已经实现了这种流媒体:.NET Core| MVC pass audio file to html5 player. Enable seeking
如果我在音频开始播放时没有立即寻求文件结束,那么搜索是有效的。我使用audio element的autoplay属性来立即开始播放音频元素有足够的数据。所以在我的情况下,当我寻求时,音频元素还没有所有数据,因此它对我的API进行了新的GET。在我的后端日志中的那种情况下有这样的例外:
失败:Microsoft.AspNetCore.Server.Kestrel [13] [1]连接ID" 0HL9V370HAF39",请求ID" 0HL9V370HAF39:00000001":应用程序抛出了未处理的异常。 [1] System.InvalidOperationException:响应内容长度不匹配:写入的字节太少(6126919中的0)。
这是我的音频控制器GET方法。
byte[] audioArray = new byte[0];
//Here I load audio file from cloud
long fSize = audioArray.Length;
long startbyte = 0;
long endbyte = fSize - 1;
int statusCode = 200;
var rangeRequest = Request.Headers["Range"].ToString();
_logger.LogWarning(rangeRequest);
if (rangeRequest != "")
{
string[] range = Request.Headers["Range"].ToString().Split(new char[] { '=', '-' });
startbyte = Convert.ToInt64(range[1]);
if (range.Length > 2 && range[2] != "") endbyte = Convert.ToInt64(range[2]);
if (startbyte != 0 || endbyte != fSize - 1 || range.Length > 2 && range[2] == "")
{ statusCode = 206; }
}
_logger.LogWarning(startbyte.ToString());
long desSize = endbyte - startbyte + 1;
_logger.LogWarning(desSize.ToString());
_logger.LogWarning(fSize.ToString());
Response.StatusCode = statusCode;
Response.ContentType = "audio/mp3";
Response.Headers.Add("Content-Accept", Response.ContentType);
Response.Headers.Add("Content-Length", desSize.ToString());
Response.Headers.Add("Content-Range", string.Format("bytes {0}-{1}/{2}", startbyte, endbyte, fSize));
Response.Headers.Add("Accept-Ranges", "bytes");
Response.Headers.Remove("Cache-Control");
var stream = new MemoryStream(audioArray, (int)startbyte, (int)desSize);
return new FileStreamResult(stream, Response.ContentType)
{
FileDownloadName = track.Name
};
我错过了一些标题还是什么?
我没有使用.NET Core 1.1获得此异常,但我不确定它是否只是巧合和/或不好的测试。但是,如果有任何人有信息,那么.NET Core中与流媒体相关的内容会发生变化,我会很感激这些信息。
答案 0 :(得分:2)
现在,当我研究更多时,我发现了这个:https://docs.microsoft.com/en-us/aspnet/core/aspnetcore-2.0看起来增强的HTTP标头支持 - 标题。它说这个
如果应用程序访问者请求带有Range Request标头的内容,ASP.NET将识别并处理该标头。如果可以部分传递所请求的内容,ASP.NET将适当地跳过并返回所请求的字节集。您不需要在方法中编写任何特殊处理程序来调整或处理此功能;它会自动为您处理。
因此,当我转移到.NET Core 1.1到2.0时,我需要的是一些清理工作,因为已经存在这些头文件的处理程序。
byte[] audioArray = new byte[0];
//Here I get my MP3 file from cloud
var stream = new MemoryStream(audioArray);
return new FileStreamResult(stream, "audio/mp3")
{
FileDownloadName = track.Name
};
答案 1 :(得分:1)
问题出现在标题中。我不确切地知道哪个标题不正确或者我的流初始化不正确但现在它正在工作。我用了这个https://stackoverflow.com/a/35920244/8081009。只有改变我使它被重命名为AudioStreamResult。然后我像这样使用它:
Response.ContentType = "audio/mp3";
Response.Headers.Add("Content-Accept", Response.ContentType);
Response.Headers.Remove("Cache-Control");
var stream = new MemoryStream(audioArray);
return new AudioStreamResult(stream, Response.ContentType)
{
FileDownloadName = track.Name
};
请注意,我将完整流传递给AudioStreamResult。
var stream = new MemoryStream(audioArray);