You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于.NET Core 7的Blazor Server应用如何实现云盘式文件夹上传?

实现Blazor Server直接文件夹上传的方案

核心思路

利用浏览器原生的directory(兼容旧版Chrome的webkitdirectory)属性让文件选择器支持文件夹选择,通过JS递归遍历文件夹内的所有文件并保留层级路径,再将文件和路径信息传递给Blazor后端,最终在服务器端重建文件夹结构完成上传。

具体实现步骤

1. 编写JS交互脚本

在wwwroot/js目录下新建folderUpload.js,写入以下代码:

window.folderUpload = {
    init: function (elementId, dotNetRef) {
        const input = document.getElementById(elementId);
        // 开启文件夹选择支持
        input.setAttribute('directory', '');
        input.setAttribute('webkitdirectory', '');
        input.setAttribute('multiple', '');
        
        input.addEventListener('change', async (e) => {
            const fileEntries = [];
            
            // 递归遍历文件夹,收集文件及相对路径
            async function traverseFileTree(item, parentPath = '') {
                if (item.isFile) {
                    const file = await item.getFile();
                    fileEntries.push({
                        file: file,
                        relativePath: parentPath + file.name
                    });
                } else if (item.isDirectory) {
                    const dirReader = item.createReader();
                    const entries = await dirReader.readEntries();
                    const currentPath = parentPath + item.name + '/';
                    for (const entry of entries) {
                        await traverseFileTree(entry, currentPath);
                    }
                }
            }
            
            // 处理选中的文件夹条目
            for (const file of e.target.files) {
                const entry = await window.webkitResolveLocalFileSystemURL(file.webkitRelativePath);
                await traverseFileTree(entry);
            }
            
            // 组装FormData传递给Blazor
            const formData = new FormData();
            fileEntries.forEach(entry => {
                formData.append('uploadFiles', entry.file, entry.relativePath);
            });
            
            // 调用Blazor后端方法处理上传
            await dotNetRef.invokeMethodAsync('ProcessFolderUpload', formData);
        });
    }
};

2. Blazor组件集成实现

以FileManager.razor组件为例,添加以下内容:

2.1 引入依赖与脚本

@inject IJSRuntime JSRuntime
@implements IAsyncDisposable

<script src="js/folderUpload.js"></script>

2.2 UI与交互逻辑

<!-- 隐藏原生文件选择框,用自定义按钮触发 -->
<input type="file" id="folderUploadInput" style="display: none;" />
<button @onclick="OpenFolderSelector" class="btn btn-primary">选择文件夹上传</button>

@code {
    private DotNetObjectReference<FileManager>? _dotNetReference;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            _dotNetReference = DotNetObjectReference.Create(this);
            // 初始化文件夹上传逻辑
            await JSRuntime.InvokeVoidAsync("folderUpload.init", "folderUploadInput", _dotNetReference);
        }
        await base.OnAfterRenderAsync(firstRender);
    }

    private void OpenFolderSelector()
    {
        // 触发隐藏的文件选择框
        var input = document.getElementById("folderUploadInput");
        input.click();
    }

    [JSInvokable]
    public async Task ProcessFolderUpload(IFormFileCollection uploadFiles)
    {
        // 服务器存储根路径,可根据实际需求调整
        var rootSavePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "user-uploads");

        foreach (var file in uploadFiles)
        {
            // 根据相对路径拼接完整存储路径
            var fullSavePath = Path.Combine(rootSavePath, file.FileName);
            // 创建文件所在的目录(如果不存在)
            var directoryPath = Path.GetDirectoryName(fullSavePath);
            if (!Directory.Exists(directoryPath))
            {
                Directory.CreateDirectory(directoryPath);
            }
            // 写入文件到服务器
            using var fileStream = new FileStream(fullSavePath, FileMode.Create);
            await file.CopyToAsync(fileStream);
        }

        // 上传完成后可添加刷新文件列表、提示用户等逻辑
        StateHasChanged();
    }

    // 释放DotNet对象引用
    public async ValueTask DisposeAsync()
    {
        _dotNetReference?.Dispose();
        await Task.CompletedTask;
    }
}

3. 关键配置与注意事项

  • 调整请求大小限制:如果上传大文件夹,需要在Program.cs中修改表单请求限制:
    builder.Services.Configure<FormOptions>(options =>
    {
        options.MultipartBodyLengthLimit = 1073741824; // 设置为1GB,根据实际需求调整
    });
    
  • 浏览器兼容性:directory属性已支持Chrome、Edge、Firefox 50+等主流浏览器,webkitdirectory用于兼容旧版Chrome,两者同时设置可覆盖更多场景。
  • 权限控制:确保服务器存储目录有读写权限,同时结合内部应用的用户权限体系,避免越权上传操作。

内容的提问来源于stack exchange,提问作者Lash

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 04:24:59