HTML5 音频搜索无法正常工作。抛出响应内容长度不匹配异常

HTML5 audio seek is not working properly. Throws Response Content-Length mismatch Exception

我正在尝试将音频文件流式传输到 Angular 应用程序,其中 html5 音频元素和 src 设置为我的 api 端点(示例。/audio/234) .我的后端是使用 .NET Core 2.0 实现的。我已经实现了这种流式传输:

如果我不在音频开始播放时立即寻找到文件结尾,Seek 就可以工作。我使用音频元素的自动播放属性立即开始播放音频元素有足够的数据。所以在我的情况下,音频元素在我寻找时还没有所有数据,所以它对我的 API 进行了新的 GET。在那种情况下,我的后端日志中有这个异常:

fail: Microsoft.AspNetCore.Server.Kestrel[13] [1] Connection id "0HL9V370HAF39", Request id "0HL9V370HAF39:00000001": An unhandled exception was thrown by the application. [1] System.InvalidOperationException: Response Content-Length mismatch: too few bytes written (0 of 6126919).

这是我的音频控制器 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 中遇到此异常,但我不确定这是否只是巧合 and/or 糟糕的测试。但是,如果有人知道 .NET Core 中是否有与流相关的更改,我将不胜感激。

问题出在 Headers。我不确切知道哪个 header 不正确,或者我的流初始化不正确,但现在它正在工作。我用这个 https://whosebug.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);

现在,当我进行更多研究时,我发现了这一点:https://docs.microsoft.com/en-us/aspnet/core/aspnetcore-2.0 查看增强型 HTTP header 支持标题。它说这个

If an application visitor requests content with a Range Request header, ASP.NET will recognize that and handle that header. If the requested content can be partially delivered, ASP.NET will appropriately skip and return just the requested set of bytes. You do not need to write any special handlers into your methods to adapt or handle this feature; it is automatically handled for you.

因此,当我迁移到 .NET Core 1.1 到 2.0 时,我需要做的只是一些清理工作,因为已经有那些 header 的处理程序。

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
};