Blazor组件上传文件夹时如何获取选中根文件夹及子文件夹名称
Blazor获取文件夹上传的根目录及子目录名称方案
Blazor内置的IBrowserFile默认没有暴露浏览器返回的文件相对路径字段,要拿到完整文件夹结构,需要通过JS互操作读取文件的webkitRelativePath属性——浏览器开启webkitdirectory选择模式时,会自动给每个文件填充这个属性,格式为选中的根文件夹/子文件夹1/子文件夹2/文件名,从这个字段就能解析出所有文件夹信息。
1. 添加JS辅助方法
在项目wwwroot目录下新建fileUpload.js,写入以下代码,用于从input DOM元素上读取带路径的文件信息:
window.fileUploadUtil = { getFilesWithPath: function (inputEl) { return Array.from(inputEl.files).map(file => ({ name: file.name, size: file.size, type: file.type, relativePath: file.webkitRelativePath, lastModified: file.lastModified })); } }
在_Host.cshtml(Blazor Server模式)或index.html(Blazor WASM模式)的body末尾引入这个JS文件:
<script src="fileUpload.js"></script>
2. 修改Razor组件代码
给InputFile组件添加元素引用,在选择文件后调用JS获取带路径的文件数据,再解析出根文件夹和所有子文件夹,完整代码如下:
@page "/uploadfolder" @inject IJSRuntime JS <InputFile @ref="uploadInput" OnChange="@HandleFolderSelect" webkitdirectory directory /> <div style="margin-top:1rem"> <p>*选中的根文件夹:*@RootFolderName</p> <p>*包含的所有文件夹:*</p> <ul> @foreach (var folder in AllFolders) { <li>@folder</li> } </ul> </div> @code { private InputFile? uploadInput; private string RootFolderName = string.Empty; private HashSet<string> AllFolders = new(); private List<FileDataWithPath> SelectedFiles = new(); // 自定义接收JS返回文件数据的模型 private class FileDataWithPath { public string Name { get; set; } = string.Empty; public long Size { get; set; } public string Type { get; set; } = string.Empty; public string RelativePath { get; set; } = string.Empty; public long LastModified { get; set; } } private async Task HandleFolderSelect(InputFileChangeEventArgs e) { SelectedFiles.Clear(); AllFolders.Clear(); RootFolderName = string.Empty; if (uploadInput?.Element is null) return; // 调用JS获取带相对路径的文件列表 SelectedFiles = await JS.InvokeAsync<List<FileDataWithPath>>( "fileUploadUtil.getFilesWithPath", uploadInput.Element); if (SelectedFiles.Count == 0) return; // 解析根文件夹名称:第一个文件路径的第一个斜杠前的内容就是根目录 var firstPath = SelectedFiles[0].RelativePath; var splitIndex = firstPath.IndexOf('/'); if (splitIndex > 0) { RootFolderName = firstPath[..splitIndex]; } // 遍历所有文件,提取所有层级的文件夹 foreach (var file in SelectedFiles) { // 按正斜杠拆分路径,浏览器返回的路径统一用正斜杠分隔 var pathSegments = file.RelativePath.Split('/', StringSplitOptions.RemoveEmptyEntries); // 最后一段是文件名,只遍历前面的文件夹段 for (int i = 0; i < pathSegments.Length - 1; i++) { var currentFolderPath = string.Join('/', pathSegments.Take(i + 1)); AllFolders.Add(currentFolderPath); } } } }
补充说明
- 浏览器出于安全限制,永远不会返回文件在用户本地的绝对路径,你拿到的所有路径都是以选中根文件夹为起点的相对路径。
AllFolders会自动去重,默认包含根文件夹,如果只需要子文件夹,过滤掉和RootFolderName值相同的项即可。- 如果后续需要读取文件内容上传,直接用
InputFileChangeEventArgs的GetMultipleFiles()方法拿到IBrowserFile流即可,可以按文件名和解析到的路径信息做匹配。
内容的提问来源于stack exchange,提问作者D T
相关产品推荐
相关产品推荐

