【问题标题】:.NET Core : IFileProvider.GetDirectoryContents recursive not working.NET Core:IFileProvider.GetDirectoryContents 递归不起作用
【发布时间】:2019-01-02 08:28:59
【问题描述】:

我想扫描一个目录(“C:/test”)并递归获取所有文件 .pdf 我创建了一个这样的提供者:

IFileProvider provider = new PhysicalFileProvider("C:/test"); // using config in my code and also tried with "C:/test/"

我在目录和子目录中放了一些pdf

这个路径有一个文件:C:/test/pdf59.pdf 另一个用 C:/test/testComplexe/pdf59.pdf

在我尝试这些行的地方,它们都返回“NotFoundDirectoryException”:

provider.getDirectoryContents(@"**")
provider.getDirectoryContents(@"*")
provider.getDirectoryContents(@"*.*")
provider.getDirectoryContents(@"**.*")    
provider.getDirectoryContents(@"pdf59.pdf")
provider.getDirectoryContents(@"*.pdf")

这行例外:

provider.getDirectoryContents(@"testComplexe")

如何查询这些递归目录和文件?谢谢

【问题讨论】:

  • 你可以使用DirectoryInfo 类然后使用 EnumerateFiles("*.pdf", SearchOption.AllDirectories) 吗?

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


【解决方案1】:

您可以编写自己的递归函数。

var files = new List<IFileInfo>();
GetFiles("C:/Tests", files);

private void GetFiles(string path, ICollection<IFileInfo> files)
{
    IFileProvider provider = new PhysicalFileProvider(path);

    var contents = provider.GetDirectoryContents("");

    foreach (var content in contents)
    {
        if (!content.IsDirectory && content.Name.ToLower().EndsWith(".pdf"))
        {
            files.Add(content);
        }
        else
        {
            GetFiles(content.PhysicalPath, files);
        }
    }
}

【讨论】:

  • 这将为每个目录创建一个新的PhysicalFileProvider。您应该使用子目录的(聚合)路径在现有提供程序实例上调用 GetDirectoryContents
【解决方案2】:

为了我未来的自己(和其他人)复制粘贴...

public static class Demo
{
    public static void FindPdfs()
    {
        var provider = new PhysicalFileProvider("c:\\temp");
        var pdfs = new List<IFileInfo>();

        provider.FindFiles(
            directory: "/",
            match: file => file.Name.EndsWith(".pdf"),
            process: pdfs.Add,
            recursive: true);

        foreach (var pdf in pdfs)
        {
            using (var stream = pdf.CreateReadStream())
            {
                // etc...
            }
        }

    }
}

public static class FileProviderExtensions
{
    /// <summary>
    /// Searches for files matching some <paramref name="match"/>, and invokes <paramref name="process"/> on them.
    /// </summary>
    /// <param name="provider">File provider</param>
    /// <param name="directory">parent directory for the search, a relative path, leading slashes are ignored,
    /// use "" or "/" for starting at the root of <paramref name="provider"/></param>
    /// <param name="match">the match predicate, if this returns true the file is passed to <paramref name="process"/></param>
    /// <param name="process">this action is invoked on <paramref name="match"/>ing files </param>
    /// <param name="recursive">if true directories a</param>
    /// <returns>the number of files <paramref name="match"/>ed and <paramref name="process"/>ed</returns>
    public static int FindFiles(this IFileProvider provider, string directory, Predicate<IFileInfo> match, Action<IFileInfo> process, bool recursive = false)
    {
        var dirsToSearch = new Stack<string>();
        dirsToSearch.Push(directory);
        var count = 0;
        while (dirsToSearch.Count > 0)
        {
            var dir = dirsToSearch.Pop();
            foreach (var file in provider.GetDirectoryContents(dir))
            {
                if (file.IsDirectory)
                {
                    if (!recursive)
                        continue;

                    var relPath = Path.Join(dir, file.Name);
                    dirsToSearch.Push(relPath);
                }
                else
                {
                    if (!match(file))
                        continue;

                    process(file);
                    count++;
                }
            }
        }

        return count;
    }
}

【讨论】:

    【解决方案3】:

    如果您只需要IFileInfo 对象的列表,这是最简单的版本。它使用扩展方法。假设您已经有一个 IFileProvider,例如已经注入的。

    var files = FileProvider.GetRecursiveFiles("/images").ToArray();
    

     

    using Microsoft.Extensions.FileProviders;
    using System.Collections.Generic;
    using System.IO;
    
    public static class FileProviderExtensions
    {
        public static IEnumerable<IFileInfo> GetRecursiveFiles(this IFileProvider fileProvider, string path, bool includeDirectories = true)
        {
            var directoryContents = fileProvider.GetDirectoryContents(path);
            foreach (var file in directoryContents)
            {
                if (file.IsDirectory)
                {
                    if (includeDirectories)
                    {
                        yield return file;
                    }
    
                    // recursively call GetFiles and return each one
                    // file.Name is the directory name alone (eg. images)
                    foreach (var f in fileProvider.GetRecursiveFiles(Path.Combine(path, file.Name), includeDirectories))
                    {
                        yield return f;
                    }
                }
                else
                {
                    // return file
                    yield return file;
                }
            }
        }
    }
    

    【讨论】:

    • 请注意,如果文件的顺序对您很重要,您可能需要切换其中一些产量的顺序。
    【解决方案4】:

    要获取根文件夹的内容(“C:/test/”),请以这种方式使用提供程序:

    var contents = provider.getDirectoryContents("")
    

    然后,您必须在 contents 中枚举结果,并对每个结果做任何您想做的事情。

    文档:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/file-providers?view=aspnetcore-2.1

    【讨论】:

    • 是的,但这不是递归模式,不会查看子目录
    猜你喜欢
    • 2017-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多