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

如何通过.NET Core Web API无压缩上传含子文件夹且保留结构的完整目录

实现方案

可以无需压缩直接上传完整文件夹并保留原有目录结构,核心依赖浏览器的webkitdirectory上传能力,前后端配合即可实现。

1. 前端配置

首先前端上传控件需要开启文件夹上传属性,提交时携带每个文件的相对路径:

<!-- 上传控件开启文件夹选择 -->
<input type="file" id="folderUpload" webkitdirectory multiple />

提交的JS逻辑示例:

const uploadInput = document.getElementById('folderUpload');
const formData = new FormData();
// 遍历选中的所有文件,传入相对路径作为第三个参数
for (const file of uploadInput.files) {
  formData.append('files', file, file.webkitRelativePath);
}
// 提交FormData到后端接口
fetch('/api/你的控制器名/import', {
  method: 'POST',
  body: formData
})

2. 后端代码改造

你现有代码的核心问题是没有处理文件的相对路径,也没有按路径创建对应层级目录,改造后代码如下:

private async Task<bool> Import()
{
    bool isSaveSuccess = false;
    // 统一设置根存储目录
    var rootSaveDir = Path.Combine(Directory.GetCurrentDirectory(), "Upload", "files1");
    if (!Directory.Exists(rootSaveDir))
    {
        Directory.CreateDirectory(rootSaveDir);
    }

    var files = Request.Form.Files;
    foreach (var file in files)
    {
        try
        {
            // file.FileName就是前端传入的相对路径,格式如"二级文件夹/三级文件夹/测试文件.txt"
            var relativePath = file.FileName;

            // 安全校验:禁止路径穿越,避免恶意上传到根目录外
            if (relativePath.Contains("..") || Path.IsPathRooted(relativePath))
            {
                continue;
            }

            // 如果需要避免文件重名,可以打开以下注释加时间戳重命名
            /*
            var fileName = Path.GetFileName(relativePath);
            var newFileName = $"{Path.GetFileNameWithoutExtension(fileName)}_{DateTime.Now.Ticks}{Path.GetExtension(fileName)}";
            relativePath = Path.Combine(Path.GetDirectoryName(relativePath), newFileName);
            */

            // 拼接完整存储路径,创建对应层级目录
            var fullSavePath = Path.Combine(rootSaveDir, relativePath);
            var fileDir = Path.GetDirectoryName(fullSavePath);
            if (!Directory.Exists(fileDir))
            {
                Directory.CreateDirectory(fileDir);
            }

            // 保存文件
            using (var stream = new FileStream(fullSavePath, FileMode.Create))
            {
                await file.CopyToAsync(stream);
            }
            isSaveSuccess = true;
        }
        catch (Exception ex)
        {
            _logger.LogError("文件保存失败:{Msg}", ex.Message);
        }
    }
    return isSaveSuccess;
}

3. 注意事项

  • 请调整Kestrel/IIS的上传大小限制,避免大文件/多文件批量上传时触发请求大小拦截
  • webkitdirectory为所有主流浏览器支持的特性,若需兼容非常老旧的浏览器,仍建议使用压缩包上传后解压的方案
  • 生产环境建议对可上传的文件类型做白名单校验,避免恶意脚本上传

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 13:57:03