ASP.NET Core控制器实现Blazor端下载wwwroot下zip文件问题咨询
问题原因
- ASP.NET Core控制器中错误使用
HttpResponseMessage作为返回值,Ok()方法会将该对象序列化为JSON返回,而非你预期的文件流,导致前端收到的是JSON数据,无法触发下载。 - Blazor端调用
GetAsync后仅拿到响应结果,未主动处理响应触发浏览器下载行为。 - 原有Blazor调用代码存在语法错误,参数拼接缺少左大括号。
控制器代码修正
ASP.NET Core的ControllerBase内置了File()方法可直接返回文件结果,无需手动构造响应对象,框架会自动处理所有下载所需的响应头:
[HttpGet("DownloadOutput")] public IActionResult Invoice(string JobId) { // 校验入参合法性,防止路径遍历攻击 if (string.IsNullOrWhiteSpace(JobId)) return BadRequest("JobId不能为空"); // 建议用Path.Combine拼接路径,兼容不同操作系统 var searchPath = Path.Combine("***PATH***", JobId); string file = Directory.EnumerateFiles(searchPath, "*.*", SearchOption.AllDirectories) .Where(n => Path.GetExtension(n).Equals(".zip", StringComparison.OrdinalIgnoreCase)) .FirstOrDefault(); if (string.IsNullOrEmpty(file) || !System.IO.File.Exists(file)) return NotFound("目标压缩包不存在"); // 仅取文件名,不要返回服务器端完整路径 var fileName = Path.GetFileName(file); // 大文件建议直接返回文件流,避免ReadAllBytes占用过多内存 // return File(new FileStream(file, FileMode.Open, FileAccess.Read), "application/octet-stream", fileName); return File(System.IO.File.ReadAllBytes(file), "application/octet-stream", fileName); }
Blazor端代码修正
方案1:直接触发浏览器原生下载(无鉴权场景推荐)
不需要调用GetAsync,直接通过JS动态创建a标签触发下载即可:
// 注入IJSRuntime后调用 var downloadUrl = $"Inventer/DownloadOutput?jobId={JobId}"; await JSRuntime.InvokeVoidAsync(@" (url) => { const a = document.createElement('a'); a.href = url; document.body.appendChild(a); a.click(); document.body.removeChild(a); } ", downloadUrl);
方案2:处理GetAsync响应(需要携带自定义请求头/鉴权场景使用)
var result = await Http.GetAsync($"Inventer/DownloadOutput?jobId={JobId}"); if (result.IsSuccessStatusCode) { var blobBytes = await result.Content.ReadAsByteArrayAsync(); await JSRuntime.InvokeVoidAsync(@" (data, fileName) => { 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; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } ", blobBytes, "下载文件.zip"); }
注意事项
- 务必对
JobId做合法性校验,禁止出现../等路径跳转字符,避免攻击者遍历服务器敏感文件 - 超过100M的大文件不要使用
ReadAllBytes,直接返回文件流即可,避免服务端内存溢出 - 如果站点配置了跨域规则,需要允许下载接口的跨域访问
内容的提问来源于stack exchange,提问作者Sonny Hansen
相关产品推荐
相关产品推荐

