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

DotNetStreamReference是否耗尽内存?Azure Blob下载异常排查

验证Azure Blob大文件下载时内存耗尽导致的OperationCanceledException

问题现象

  • 下载约140MB的Azure Blob文件时,未主动取消操作却抛出OperationCanceledException
  • 小于60MB的小文件可正常下载,生产环境运行无异常
  • 本地使用低配置笔记本,经常出现存储空间不足的情况

使用的代码

后端C#代码

try 
{
   var fileStream = await _blobServices.ReturnBlobStreamAsync(blobName,_downloadProgress.CancellationTokenSrc.Token);
   using var streamRef = new DotNetStreamReference(stream: fileStream);
   _downloadProgress.CancellationTokenSrc.Token.ThrowIfCancellationRequested();
   await jsRuntime.InvokeVoidAsync("downloadFileFromStream", fullFileName, streamRef);
}
catch (OperationCanceledException ex)
{
    Logger.LogWarning("Download was cancelled : " + ex);
}

前端JS代码

async function downloadFileFromStream(fileName, contentStreamReference) {
    const arrayBuffer = await contentStreamReference.arrayBuffer();
    const blob = new Blob([arrayBuffer]);
    const url = URL.createObjectURL(blob);
    const anchorElement = document.createElement('a');
    anchorElement.href = url;
    anchorElement.download = fileName ?? '';
    anchorElement.click();
    anchorElement.remove();
    URL.revokeObjectURL(url);
}

验证内存耗尽猜想的方法

  • 实时监控进程内存:下载大文件时,打开任务管理器(Windows)或活动监视器(Mac),观察应用进程的内存占用变化。如果内存占用飙升至接近系统可用内存上限后触发异常,即可初步确认内存不足导致取消操作。
  • 添加内存日志记录:在C#代码中插入内存监控逻辑,记录关键节点的内存使用情况:
    // 获取流前记录内存
    var memoryBefore = GC.GetTotalMemory(false);
    Logger.LogInformation($"内存占用(获取流前):{memoryBefore / 1024 / 1024} MB");
    
    var fileStream = await _blobServices.ReturnBlobStreamAsync(blobName,_downloadProgress.CancellationTokenSrc.Token);
    
    // 获取流后记录内存
    var memoryAfterStream = GC.GetTotalMemory(false);
    Logger.LogInformation($"内存占用(获取流后):{memoryAfterStream / 1024 / 1024} MB");
    
    using var streamRef = new DotNetStreamReference(stream: fileStream);
    await jsRuntime.InvokeVoidAsync("downloadFileFromStream", fullFileName, streamRef);
    
    // 下载完成后记录内存(强制GC)
    var memoryAfterDownload = GC.GetTotalMemory(true);
    Logger.LogInformation($"内存占用(下载完成后):{memoryAfterDownload / 1024 / 1024} MB");
    
    若日志显示内存随下载过程大幅增长,且接近系统内存限制时抛出异常,可验证猜想。
  • 模拟低内存环境:通过系统工具(如Windows资源监视器)或第三方工具限制应用的内存配额,再尝试下载大文件。如果限制内存后小文件也开始抛出相同异常,即可确认内存不足是问题根源。
  • 检查Blob流实现:查看ReturnBlobStreamAsync的内部逻辑,如果是将整个Blob内容加载到内存流中返回,大文件必然会耗尽内存。修改为返回流式读取的流(如Azure SDK的BlobOpenReadStreamAsync返回的流)后测试,若问题消失,可反向验证原猜想。

内容的提问来源于stack exchange,提问作者Nishant Sharma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 22:16:32