无法通过Web Api从Azure Storage向Angular前端返回启用宏的Excel文件
问题解决:从Azure Storage下载带宏的Excel文件时出现“Cannot access a closed Stream.”错误
错误根源
- API的
finally块提前释放了memoryStream,但ASP.NET Core的FileResult需要在后续请求处理阶段读取该流,此时流已关闭导致报错。 - .xlsm文件的MIME类型使用错误,应使用专属类型而非普通xlsx的类型。
- 前端
responseType配置位置错误,不应放在headers层级。 - API中硬编码文件名,忽略了传入的参数,不符合设计逻辑。
修正后的API代码(C#)
[HttpGet("download/{fileSource}")] public async Task<FileResult> DownloadFile([FromRoute] string fileSource) { var storageAccount = CloudStorageAccount.Parse(_storageConnectionString); var blobClient = storageAccount.CreateCloudBlobClient(); var container = blobClient.GetContainerReference("documents"); var blockBlob = container.GetBlockBlobReference(fileSource); var memoryStream = new MemoryStream(); try { await blockBlob.DownloadToStreamAsync(memoryStream); memoryStream.Position = 0; // 使用xlsm对应的正确MIME类型 return File(memoryStream, "application/vnd.ms-excel.sheet.macroEnabled.12", fileSource); } catch (Exception ex) { throw; } // 移除手动Dispose:ASP.NET Core会自动处理FileResult中流的释放 }
修正后的前端代码(Angular)
1. 修正请求选项配置
// responseType需放在请求选项根层级,而非headers内 getDownloadFileHeaderOptions = { responseType: 'blob' as 'json' // 类型断言避免TS类型报错 };
2. 修正下载方法
downloadFile(fileSource: string): Observable<Blob> { let url = `${environment.APIURL}docs/download/${fileSource}`; return this.http.get<Blob>(url, this.getDownloadFileHeaderOptions) .pipe( tap(response => { // 使用xlsm专属MIME类型创建Blob const blob = new Blob([response], { type: 'application/vnd.ms-excel.sheet.macroEnabled.12' }); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = fileSource; a.click(); // 释放URL对象,避免内存泄漏 window.URL.revokeObjectURL(url); }) ); }
关键说明
- 流的释放逻辑:ASP.NET Core的
FileResult会在响应发送完成后自动释放流资源,手动在finally块中Dispose会导致流提前关闭。 - MIME类型匹配:.xlsm文件必须使用
application/vnd.ms-excel.sheet.macroEnabled.12类型,否则可能导致文件无法正常打开或宏丢失。 - 前端配置注意:Angular HttpClient的
responseType是请求选项的直接属性,放在headers中会被当作普通请求头,无法正确解析响应为Blob。 - 内存泄漏处理:下载完成后调用
window.URL.revokeObjectURL(url)释放临时URL对象,避免浏览器内存泄漏。
内容的提问来源于stack exchange,提问作者Code Ratchet
相关产品推荐
相关产品推荐

