首页 文章

检查FTP上的文件或文件夹

提问于
浏览
1

我从FTP读取文件/文件夹列表 .

问题是我不知道是文件还是文件夹 . 目前我正在检查字符串是否有扩展名 . 如果是,那么它是文件,否则它是文件夹 . 但这还不够好,它可以存在没有扩展名的文件和带扩展名的文件夹(例如文件夹名称可以是FolderName.TXT)

这是我用来列出文件夹内容的代码:

public async Task<CollectionResult<string>> ListFolder(string path)
{
    try
    {
        FtpWebRequest ftpRequest = null;
        var fileNames = new List<string>();
        var res = new CollectionResult<string>();
        ftpRequest = ftpBuilder.Create(path, WebRequestMethods.Ftp.ListDirectory);
        using (var ftpResponse = (FtpWebResponse)await ftpRequest.GetResponseAsync())
        using (var ftpStream = ftpResponse.GetResponseStream())
        using (var streamReader = new StreamReader(ftpStream, Encoding.UTF8))
        {
            string fileName = streamReader.ReadLine();
            while (!string.IsNullOrEmpty(fileName))
            {
                fileNames.Add(Path.Combine(path, fileName.Substring(fileName.IndexOf('/') + 1, fileName.Length - fileName.IndexOf('/') - 1)));
                fileName = streamReader.ReadLine();
            }
        }
        ftpRequest = null;
        res.ListResult = fileNames;
        return res;
    }
    catch (Exception e)
    {
        e.AddExceptionParameter(this, nameof(path), path);
        throw;
    }
}

如果我能在循环中检测文件或文件夹是否最好,那将是最好的,但是不可能仅从字符串中执行此操作 .

谢谢您的帮助 .


编辑

我发现了类似的问题 . C# FTP, how to check if a Path is a File or a Directory?但问题很老,没有很好的解决方案 .


编辑:解决方案

public async Task<CollectionResult<Tuple<string, bool>>> ListFolder(string path)
        {
            try
            {
                FtpWebRequest ftpRequest = null;
                var fileNames = new CollectionResult<Tuple<string, bool>>();
                fileNames.ListResult = new List<Tuple<string, bool>>();
                if (!(IsFtpDirectoryExist(path)))
                {
                    throw new RemoteManagerWarningException(ErrorKey.LIST_DIRECTORY_ERROR, fileNames.ErrorMessage = $"path folder {path} not exists");
                }
                ftpRequest = ftpBuilder.Create(path, WebRequestMethods.Ftp.ListDirectoryDetails);
                using (var ftpResponse = (FtpWebResponse)await ftpRequest.GetResponseAsync())
                using (var ftpStream = ftpResponse.GetResponseStream())
                using (var streamReader = new StreamReader(ftpStream, Encoding.UTF8))
                {
                    while (!streamReader.EndOfStream)
                    {
                        string line = streamReader.ReadLine();
                        string[] tokens = line.Split(new[] { ' ' }, 9, StringSplitOptions.RemoveEmptyEntries);
                        // is number:
                        Regex rgx = new Regex(@"^[\d\.]+$");
                        var isExternalFtpOrUnixDirectoryStyle = !(rgx.IsMatch(line[0].ToString()));
                        string name = string.Empty;
                        bool isFolder = false;

                        if (isExternalFtpOrUnixDirectoryStyle)
                        {
                            name = tokens[8];
                            var permissions = tokens[0];
                            isFolder = permissions[0] == 'd';
                        }
                        else
                        {
                            tokens = line.Split(new[] { ' ' }, 4, StringSplitOptions.RemoveEmptyEntries);
                            name = tokens[3];
                            isFolder = tokens[2] == "<DIR>";
                        }
                        name = Path.Combine(path, name);
                        Tuple<string, bool> tuple = new Tuple<string, bool>(name, isFolder);
                        fileNames.ListResult.Add(tuple);                           
                    }
                }
                ftpRequest = null;
                return fileNames;
            }
            catch (Exception e)
            {
                e.AddExceptionParameter(this, nameof(path), path);
                throw;
            }
        }

2 回答

  • 1

    无法使用 FtpWebRequest 或.NET Framework的任何其他内置功能以可移植的方式识别目录条目是否是文件的子目录 . 遗憾的是 FtpWebRequest 不支持 MLSD 命令,这是在FTP协议中使用文件属性检索目录列表的唯一可移植方式 . 另见Checking if object on FTP server is file or directory .

    你的选择是:

    • 对文件名执行操作,该文件名对于文件肯定会失败并且对目录成功(反之亦然) . 即你可以尝试下载"name" . 如果成功,它's a file, if that fails, it'是一个目录 .

    • 您可能很幸运,在您的具体情况下,您可以通过文件名告诉目录中的文件(即所有文件都有扩展名,而子目录则没有)

    • 您使用长目录列表( LIST command = ListDirectoryDetails 方法)并尝试解析特定于服务器的列表 . 许多FTP服务器使用* nix样式列表,您可以在条目的最开头通过 d 识别目录 . 但是许多服务器使用不同的格式 .

    有关实现解析的一些示例,请参阅:


    如果要避免解析特定于服务器的目录列表格式的麻烦,请使用支持 MLSD 命令和/或解析各种 LIST 列表格式的第三方库;和递归下载 .

    例如,使用WinSCP .NET assembly,您可以使用Sesssion.ListDirectory

    // Setup session options
    SessionOptions sessionOptions = new SessionOptions
    {
        Protocol = Protocol.Ftp,
        HostName = "example.com",
        UserName = "user",
        Password = "mypassword",
    };
    
    using (Session session = new Session())
    {
        // Connect
        session.Open(sessionOptions);
    
        RemoteDirectoryInfo directory = session.ListDirectory("/home/martin/public_html");
    
        foreach (RemoteFileInfo fileInfo in directory.Files)
        {
            if (fileInfo.IsDirectory)
            {
                // directory
            }
            else
            {
                // file
            }
        }
    }
    

    在内部,如果服务器支持,WinSCP使用 MLSD 命令 . 如果没有,它使用 LIST 命令并支持许多不同的列表格式 .

    (我是WinSCP的作者)

  • 2

    使用FTP'list'命令并解析权限和目录指示符 .

相关问题