.NET 7 API通过Memory Stream下载Azure Blob文件时遇超时错误
问题解决:.NET 7 API从Azure Blob下载文件时出现“Time outs are not supported in this stream”错误
问题根源
你当前的代码将Blob文件先下载到MemoryStream再复制返回,这种方式不仅会把整个文件加载到内存(大文件场景下内存占用极高),还会因为MemoryStream本身不支持超时操作,导致ASP.NET Core处理响应时抛出超时相关的500错误。
修复方案
直接获取Azure Blob的原生下载流,让ASP.NET Core直接将流传输给客户端,既节省内存,又解决流超时的兼容性问题。修改后的代码如下:
修改后的Service.cs
public async Task<IResult> GetBlob(string blobName) { BlobClient blobClient = _blobServiceClient .GetBlobContainerClient("root") .GetBlobClient(blobName); try { // 检查文件是否存在,返回更合理的404错误 if (!await blobClient.ExistsAsync()) { return Results.NotFound("指定文件不存在"); } // 直接获取Blob的只读流,无需加载到内存 var blobStream = await blobClient.OpenReadAsync(); // 使用ASP.NET Core内置方法返回文件流 return Results.File(blobStream, "application/octet-stream", blobName); } catch (Exception ex) { Console.WriteLine($"发生错误: {ex.Message}"); // 明确返回500状态码,让客户端感知错误 return Results.StatusCode(StatusCodes.Status500InternalServerError); } }
可选优化:Endpoint.cs补充状态码声明
为了让API文档(如Swagger)更准确,可在端点声明中补充可能的响应状态码:
public IEndpointRouteBuilder MapEndpoints(IEndpointRouteBuilder endpoints) { endpoints.MapGet("getBlob/{blobname}", async (string blobName, IApplicationFormService applicationFormService) => await applicationFormService.GetBlob(blobName)) .ProducesFile("application/octet-stream") .Produces(StatusCodes.Status404NotFound) .Produces(StatusCodes.Status500InternalServerError); return endpoints; }
关键修改点说明
- 避免内存加载:使用
OpenReadAsync获取Blob原生流,无需将整个文件加载到内存,大幅降低内存占用并提升响应速度。 - 自动管理流生命周期:
Results.File方法会自动处理流的释放,无需手动用using包裹,避免流提前释放的问题。 - 更合理的错误反馈:添加文件存在性检查返回404,异常时返回500状态码,让客户端能正确识别错误类型。
内容的提问来源于stack exchange,提问作者svalaie
相关产品推荐
相关产品推荐

