如何从Blazor项目wwwroot文件夹下载关联数据库的文件?
问题解决:Blazor下载wwwroot文件时本地资源加载错误
问题背景
在Radzen Blazor页面创建按钮,用于下载wwwroot目录下关联SQL Server Tbl_Tickets表某行的文件,文件路径和文件名存储在表中,通过ticket_Id筛选文件,但触发下载时出现错误:
Not allowed to load local resource: file:///C:/Users/Administrator/source/repos/Tickets/V05/wwwroot
现有代码
Blazor页面按钮代码
<RadzenRow> <button @onclick="DownloadFileFromURL"> Download Files</button> </RadzenRow>
JS下载函数
<script> window.triggerFileDownload = (fileName, url) => { const anchorElement = document.createElement('a'); anchorElement.href = url; anchorElement.download = fileName ?? ''; anchorElement.click(); anchorElement.remove(); } </script>
C#逻辑代码
@inject IJSRuntime JS @inject IWebHostEnvironment environment @code { private async Task DownloadFileFromURL() { var fileName = $"{tblTicket.AttchedFileName}"; var fileURL = $"{environment.WebRootPath}"; await JS.InvokeVoidAsync("triggerFileDownload", fileName, fileURL); } }
错误原因
environment.WebRootPath获取的是服务器本地文件路径(如C:/xxx/wwwroot),直接传给前端JS会被浏览器拦截——浏览器禁止直接访问本地文件系统路径,必须通过相对URL或Web可访问的路径来访问wwwroot内的资源。
解决方法
方法1:构建Web可访问的相对路径
wwwroot是Blazor的静态文件根目录,里面的文件可以通过相对URL访问(如/文件名)。修改C#代码:
private async Task DownloadFileFromURL() { // 构建相对URL,直接指向wwwroot下的目标文件 var fileUrl = $"/{tblTicket.AttchedFileName}"; await JS.InvokeVoidAsync("triggerFileDownload", tblTicket.AttchedFileName, fileUrl); }
方法2:通过后端API返回文件流(适合权限验证场景)
如果文件需要权限控制,不能直接通过静态URL访问,可创建API接口返回文件流:
- 添加API控制器:
[ApiController] [Route("api/[controller]")] public class FileController : ControllerBase { private readonly IWebHostEnvironment _env; public FileController(IWebHostEnvironment env) { _env = env; } [HttpGet("download")] public IActionResult DownloadFile(string fileName) { var filePath = Path.Combine(_env.WebRootPath, fileName); if (!System.IO.File.Exists(filePath)) { return NotFound(); } var fileStream = new FileStream(filePath, FileMode.Open); var contentType = "application/octet-stream"; return File(fileStream, contentType, fileName); } }
- 修改Blazor的C#代码调用API:
private async Task DownloadFileFromURL() { var fileUrl = $"/api/file/download?fileName={Uri.EscapeDataString(tblTicket.AttchedFileName)}"; await JS.InvokeVoidAsync("triggerFileDownload", tblTicket.AttchedFileName, fileUrl); }
注意事项
- 确保
tblTicket.AttchedFileName仅包含文件名(不含路径),且文件确实存在于wwwroot目录下。 - 如果文件存放在wwwroot的子目录中,相对URL需包含子路径(如
/files/{tblTicket.AttchedFileName})。
内容的提问来源于stack exchange,提问作者Ibrahim-Amer
相关产品推荐
相关产品推荐

