.NET 6 Web API部署Azure后audio/mpeg流无法播放问题求助
需求是将带自定义端口的HTTP在线电台流(示例:http://44.44.44.44:56/stream/1),通过Azure WebApp以无自定义端口的HTTPS方式代理暴露(示例:https://coolradio.azurewebsites.net/api/radio/AzureStream)。
本地使用.NET 6 Web API实现的两种代理代码均正常运行,但部署到Azure WebApp后,其他控制器可正常访问,唯独音频流无法播放——尽管HTTP响应头、请求头及流内容与本地完全一致。之前.NET Core版本部署到Azure时功能正常,升级至.NET 6后Azure端失效。
本地可用的两种实现代码:
HttpClient实现
public async Task<IActionResult> AzureStream() { var sourceUrl = "http://44.44.44.44:56/stream/1"; var mimeType = "audio/mpeg"; var client = new HttpClient(); var sourceStream = await client.GetStreamAsync(sourceUrl); var fileStreamResult = new FileStreamResult(sourceStream, mimeType); return fileStreamResult; }
TcpClient实现
var sourceUri = new Uri(sourceUrl); var sourceClient = new TcpClient(); string requestString = $"GET {sourceUri.PathAndQuery} HTTP/1.1\r\n" + $"Host: {sourceUri.Host}\r\n" + "Connection: keep-alive\r\n" + "\r\n"; await sourceClient.ConnectAsync(sourceUri.Host, sourceUri.Port); var sourceStream = sourceClient.GetStream(); var writer = new StreamWriter(sourceStream); writer.Write(requestString); writer.Flush(); var fileStreamResult = new FileStreamResult(sourceStream, mimeType); return fileStreamResult;
针对.NET 6在Azure WebApp上的流式代理问题,可通过以下步骤修复:
1. 优化HttpClient配置,避免自动缓冲
.NET 6默认的HttpClient行为可能导致响应被缓冲,而音频流需要逐块流式传输。建议通过IHttpClientFactory配置单例HttpClient,并禁用连接关闭,确保长连接:
在Program.cs中添加HttpClient配置:
builder.Services.AddHttpClient("RadioProxy", client => { client.DefaultRequestHeaders.ConnectionClose = false; client.DefaultRequestHeaders.Add("Connection", "keep-alive"); });
2. 修改控制器代码,确保流式传输正确
注入IHttpClientFactory,使用HttpCompletionOption.ResponseHeadersRead仅读取响应头后立即获取流,同时在响应中添加必要的头信息禁用缓冲:
private readonly IHttpClientFactory _httpClientFactory; public RadioController(IHttpClientFactory httpClientFactory) { _httpClientFactory = httpClientFactory; } public async Task<IActionResult> AzureStream() { var sourceUrl = "http://44.44.44.44:56/stream/1"; var client = _httpClientFactory.CreateClient("RadioProxy"); // 仅读取响应头,不缓冲整个响应体 var response = await client.GetAsync(sourceUrl, HttpCompletionOption.ResponseHeadersRead); response.EnsureSuccessStatusCode(); // 获取源流的Content-Type, fallback到audio/mpeg var contentType = response.Content.Headers.ContentType?.ToString() ?? "audio/mpeg"; // 禁用缓存,强制流式传输 Response.Headers.Add("Cache-Control", "no-cache"); Response.Headers.Add("Transfer-Encoding", "chunked"); Response.Headers.Add("Connection", "keep-alive"); // 获取流并返回 var stream = await response.Content.ReadAsStreamAsync(); return new FileStreamResult(stream, contentType); }
3. 检查Azure WebApp的出站端口权限
Azure WebApp对出站端口有默认限制,需确认目标端口(56)在允许列表中:
- 登录Azure门户,进入目标WebApp -> 网络 -> 出站流量
- 检查是否允许访问目标IP和端口56,若需自定义端口,可通过VNet集成或添加出站规则配置
4. 排除响应压缩中间件干扰
如果启用了响应压缩,可能会破坏流式音频的传输,可针对音频MIME类型禁用压缩:
在Program.cs中修改响应压缩配置:
builder.Services.AddResponseCompression(options => { options.ExcludeMimeTypes = new[] { "audio/mpeg", "audio/*" }; });
内容的提问来源于stack exchange,提问作者Mando

