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
相关产品推荐
相关产品推荐

