【问题标题】:Is there any way to upload a folder(have subfolders also) instead of file using .netcore web api有没有办法使用.netcore web api上传文件夹(也有子文件夹)而不是文件
【发布时间】:2023-12-02 22:46:01
【问题描述】:

是否可以使用 .netcore webapi 上传具有相同文件夹结构的整个文件夹。我知道我们可以压缩并上传,然后解压缩,只是想知道另一种上传方式,而不是压缩

目前我已经更新了控制器如下,这个逻辑不考虑上传文件夹

    private async Task<bool> Import()
    {
        bool isSaveSuccess = false;
        string fileName;
        var files = Request.Form.Files;
        foreach (var file in files)
        {
            try
            {
                var extn = "." + file.FileName.Split('.')[file.FileName.Split('.').Length - 1];
                fileName = file.FileName + DateTime.Now.Ticks + extn;
                //fileName = Path.Combine(file.FileName, DateTime.Now.Ticks + extn);

                var pathBuilt = Path.Combine(Directory.GetCurrentDirectory(), "Upload\\files1");

                if (!Directory.Exists(pathBuilt))
                {
                    Directory.CreateDirectory(pathBuilt);
                }

                var path = Path.Combine(Directory.GetCurrentDirectory(), "Upload\\files1", fileName);

                using (var stream = new FileStream(path, FileMode.Create))
                {
                    await file.CopyToAsync(stream);
                }
                isSaveSuccess = true;
            }
            catch
            {
                _logger.LogError("Request failed: " + "err");

            }
        }
        return isSaveSuccess;
    }

【问题讨论】:

  • 你的意思是像表单上传吗?或者更高级的东西?
  • 是的,使用表单上传我只能获取文件(. 或 zip 文件),但不能获取文件夹

标签: c# asp.net-core asp.net-core-webapi


【解决方案1】:

是的,应该可以。看看webkitdirectory属性:https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/webkitdirectory

这将允许您选择一个或多个文件夹,以便您可以遍历用户选择的内部内容。如您所见,这是一个“原生”功能,不限于 asp.net 或 c#。

<input type="file" id="files" name="files" webkitdirectory multiple />
<ul id="listing"></ul>
document.getElementById("filepicker").addEventListener("change", function(event) {
  let output = document.getElementById("listing");
  let files = event.target.files;

  for (let i=0; i<files.length; i++) {
    let item = document.createElement("li");
    item.innerHTML = files[i].webkitRelativePath;
    output.appendChild(item);
  };
}, false);

从演示代码中可以看出,您可以通过调用.webkitRelativePath获取相对路径,因此在您的目标上重新创建文件夹结构应该没有问题。

请注意,此功能在 50 以下的 android 上的 Internet Explorer 和 Firefox 版本上本机不可用。

使用子文件夹保存文件的更新

这里是一个简单的上传示例,上传任意数量的表单文件并将它们保存到磁盘,同时保持相对文件夹结构。

首先更改您的控制器构造函数以获取您当前的环境:

private readonly IWebHostEnvironment _env;
public HomeController(IWebHostEnvironment environment)
{
   _env = environment;
}

然后相应地修改您的上传逻辑:

[HttpPost]
public async Task<IActionResult> Upload([FromForm] IFormFileCollection files)
{
   //target in wwwroot for static files
   string targetFolder = Path.Combine(_env.WebRootPath, "uploads");
   foreach (IFormFile file in files)
   {
      if (file.Length <= 0) continue;

      //fileName is the the fileName including the relative path
      string path = Path.Combine(targetFolder, file.FileName);

      //check if folder exists, create if not
      var fi = new FileInfo(path);
      fi.Directory?.Create();

      //copy to target
      using var fileStream = new FileStream(path, FileMode.Create);
      await file.CopyToAsync(fileStream);
   }
   return View("Index");
}

这将导致您的文件夹及其所有子文件夹被保存到应用程序内的wwwroot/uploads/ 文件夹中:

wwwroot/
|
|-uploads
        |-MyFolder
                 |- File1.jpg
                 |- File2.jpg
                 |- MyFolder2
                            |- File3.jpg

我建议将它们保存在不同的地方,因为重新部署可能会首先清除应用程序文件夹,具体取决于您的部署策略(xcopy、github 操作、azure 管道、容器......)

【讨论】:

  • 似乎上面的答案在 java 脚本中,我正在寻找的是 C#(.Netcore 3.1) 用于我的后端。将文件夹存储在服务器中
  • 如果你给我一个起点,你被困在哪里,我相信我可以想出一些东西,但你的问题给了我们一个空白,所以我的解决方案最早出现在用户可以做某事。
  • 对不起,部分信息,目前我已经在控制器中编写了上述逻辑,我已经更新了我的问题
  • @Lax 我已经用缺少的 asp.net 核心位更新了我的答案,
  • 非常感谢您的回答,这正是我要找的。赞赏! @马可