Blazor上传300MB文件时OpenReadStream内存占用过高且无法释放
问题分析
当前代码直接将300MB文件一次性读入byte[],在Blazor WebAssembly环境下会触发双重内存分配:一是.NET侧的byte[]占用,二是浏览器JS runtime处理文件流时的额外内存开销,两者叠加导致内存暴增。另外,.NET 6.0.101版本的Blazor WASM在IBrowserFile流处理上存在内存泄漏BUG,即使手动调用GC.Collect()也无法释放JS侧残留的内存。
解决方案
1. 采用流式上传,避免一次性加载整个文件到内存
不要将文件全部读入byte[],直接将IBrowserFile的流传入MultipartFormDataContent,通过分块传输减少内存占用:
private async Task<bool> UploadFile(IReadOnlyCollection<IBrowserFile> imgFiles) { filesComponent.clearDragClass(); using var multipartContent = new MultipartFormDataContent(); foreach (var imgFile in imgFiles) { var streamContent = new StreamContent(imgFile.OpenReadStream(1000000000)); streamContent.Headers.ContentType = new MediaTypeHeaderValue(imgFile.ContentType); multipartContent.Add(streamContent, "uploadedFiles", imgFile.Name); } // 发送上传请求 using var httpClient = new HttpClient(); var response = await httpClient.PostAsync("你的服务器上传接口地址", multipartContent); return response.IsSuccessStatusCode; }
这种方式只会保留当前传输块的内存占用,不会一次性加载整个300MB文件。
2. 升级.NET版本至6.0.105及以上
.NET 6.0.101存在Blazor WASM文件流处理的内存泄漏问题,微软在后续补丁版本中已修复该BUG。升级到最新的.NET 6补丁版本(或直接升级至.NET 7/8),可解决上传后内存无法释放的问题。
3. 手动释放JS侧资源(临时兼容方案)
如果暂时无法升级.NET版本,可通过JS互操作强制释放浏览器侧的文件引用:
首先在wwwroot/index.html中添加JS函数:
window.releaseFileReference = function(fileRef) { if (fileRef) { URL.revokeObjectURL(fileRef); } };
然后在C#上传完成后调用该函数:
// 上传完成后遍历文件释放JS侧资源 foreach (var imgFile in imgFiles) { await JS.InvokeVoidAsync("releaseFileReference", imgFile.Reference); }
关键注意事项
- Blazor WASM环境下,处理大文件必须优先采用流式方案,避免一次性加载文件到内存。
- 及时释放不再使用的流对象和JS侧引用,降低内存泄漏风险。
内容的提问来源于stack exchange,提问作者Elnur
相关产品推荐
相关产品推荐

