You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 6 Web API部署Azure后audio/mpeg流无法播放问题求助

问题:Azure WebApp上.NET 6 Web API无法代理音频流(本地正常)

需求是将带自定义端口的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 23:05:18