Blazor 实现文件下载主要有两种场景:服务端生成/读取文件后返回(常用),以及前端直接触发浏览器下载(如 Blob)。核心是让浏览器拿到文件内容并触发保存对话框,关键在于正确设置响应头和传输方式。
服务端返回文件(推荐,适用于大多数情况)
这是最稳妥的方式,尤其适合需要权限校验、动态生成、大文件流式传输等场景。Blazor Server 或 Blazor WebAssembly 都可通过 HTTP 请求调用后端 API 下载文件。
后端(如 ASP.NET Core Controller)返回FileResult,例如
FileStreamResult、
PhysicalFileResult或
FileContentResult确保设置正确的
Content-Disposition响应头(含
attachment; filename="xxx"),否则浏览器可能尝试内嵌打开而非下载 Blazor 客户端用
NavigationManager.NavigateTo(url, forceLoad: true)直接跳转到下载接口 URL——这是最简单可靠的方式,无需 JS 互操作
前端触发下载(适合小文件或已加载的二进制数据)
当文件内容已在前端(比如用户上传后处理、JSON 导出为 CSV、Canvas 导出图片),可用 JavaScript 互操作生成 Blob 并下载。
在wwwroot/index.html或
wwwroot/_content/YourApp/引入轻量 JS 函数(或用
IJSRuntime注入) 典型 JS 逻辑:
const blob = new Blob([data], { type: 'application/octet-stream' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'filename.txt'; a.click(); URL.revokeObjectURL(url);
Blazor 中调用:await JS.InvokeVoidAsync("downloadBlob", byteData, "report.xlsx");(注意:byteData需是
byte[]或
ArrayBuffer,WebAssembly 下建议转为
ArrayBuffer传递)
避免常见坑
很多问题不是逻辑错,而是细节疏忽:
Blazor Server 下不要在组件中直接写Response(无 HttpContext),必须走标准 HTTP 接口 WebAssembly 中不能访问服务器文件系统,所有文件操作必须经 API 或前端构造 大文件别一次性加载到内存再传给 JS,优先用服务端流式响应 +
NavigateTo中文文件名需 URL 编码(后端用
Uri.EscapeDataString(filename)),并在
Content-Disposition中加
filename*=UTF-8''...格式
基本上就这些。服务端下载走
NavigateTo最省心;前端下载控制灵活但要注意大小和编码。选哪种取决于你的文件来源和业务约束。
