【问题标题】:List names of files in FTP directory and its subdirectories列出 FTP 目录及其子目录中的文件名
【发布时间】:2016-12-12 21:58:35
【问题描述】:

我在网上搜索过,但没有找到任何结果。实际上,我想获取rootDirectorySub Directory 中所有文件的名称。我尝试了下面的代码,但它只给了我 FTP 的root 中的文件。

我在 FTP 中的文件夹如下所示:

/ds/product/Jan/
/ds/subproduct/Jan/
/ds/category/Jan/

我试过的代码:

FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create("ftp://" + FtpIP);
ftpRequest.Credentials = new NetworkCredential(FtpUser, FtpPass);
ftpRequest.Method = WebRequestMethods.Ftp.ListDirectory;
FtpWebResponse response = (FtpWebResponse)ftpRequest.GetResponse();
StreamReader streamReader = new StreamReader(response.GetResponseStream());

List<string> directories = new List<string>();

string line = streamReader.ReadLine();
while (!string.IsNullOrEmpty(line))
{
   // directories.Add(line);
    line = streamReader.ReadLine().ToString();
    MessageBox.Show(line);
}

streamReader.Close();

【问题讨论】:

    标签: c# .net ftp ftpwebrequest


    【解决方案1】:

    在没有任何外部库的情况下实现这一点并不容易。不幸的是,.NET Framework 和 PowerShell 都没有明确支持在 FTP 目录中递归列出文件。

    你必须自己实现:

    • 列出远程目录
    • 迭代条目,递归到子目录 - 再次列出它们,等等。

    棘手的部分是从子目录中识别文件。使用 .NET Framework (FtpWebRequest) 无法以可移植的方式做到这一点。不幸的是,.NET Framework 不支持MLSD 命令,这是在 FTP 协议中检索具有文件属性的目录列表的唯一可移植方式。另见Checking if object on FTP server is file or directory

    您的选择是:

    • 对文件名执行操作,对于文件肯定会失败,而对于目录会成功(反之亦然)。 IE。您可以尝试下载“名称”。
    • 您可能很幸运,在您的特定情况下,您可以通过文件名来区分目录中的文件(即,您的所有文件都有扩展名,而子目录没有)
    • 您使用长目录列表(LIST 命令 = ListDirectoryDetails 方法)并尝试解析特定于服务器的列表。许多 FTP 服务器使用 *nix 样式的列表,您可以在其中通过条目开头的 d 标识目录。但是许多服务器使用不同的格式。以下示例使用这种方法(假设为 *nix 格式)
    static void ListFtpDirectory(string url, NetworkCredential credentials)
    {
        WebRequest listRequest = WebRequest.Create(url);
        listRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
        listRequest.Credentials = credentials;
    
        List<string> lines = new List<string>();
    
        using (WebResponse listResponse = listRequest.GetResponse())
        using (Stream listStream = listResponse.GetResponseStream())
        using (StreamReader listReader = new StreamReader(listStream))
        {
            while (!listReader.EndOfStream)
            {
                string line = listReader.ReadLine();
                lines.Add(line);
            }
        }
    
        foreach (string line in lines)
        {
            string[] tokens =
                line.Split(new[] { ' ' }, 9, StringSplitOptions.RemoveEmptyEntries);
            string name = tokens[8];
            string permissions = tokens[0];
    
            if (permissions[0] == 'd')
            {
                Console.WriteLine($"Directory {name}");
    
                string fileUrl = url + name;
                ListFtpDirectory(fileUrl + "/", credentials);
            }
            else
            {
                Console.WriteLine($"File {name}");
            }
        }
    }
    

    使用如下函数:

    NetworkCredential credentials = new NetworkCredential("user", "mypassword");
    string url = "ftp://ftp.example.com/directory/to/list/";
    ListFtpDirectory(url, credentials);
    

    如果您想避免解析服务器特定目录列表格式的麻烦,请使用支持MLSD 命令和/或解析各种LIST 列表格式的第三方库。

    例如使用WinSCP .NET assembly,您可以通过调用Session.EnumerateRemoteFiles 递归地列出整个目录:

    // Setup session options
    var sessionOptions = new SessionOptions
    {
        Protocol = Protocol.Ftp,
        HostName = "ftp.example.com",
        UserName = "user",
        Password = "mypassword",
    };
    
    using (var session = new Session())
    {
        // Connect
        session.Open(sessionOptions);
    
        // Enumerate files
        var options =
            EnumerationOptions.EnumerateDirectories | EnumerationOptions.AllDirectories;
        IEnumerable<RemoteFileInfo> fileInfos =
            session.EnumerateRemoteFiles("/directory/to/list", null, options);
        foreach (var fileInfo in fileInfos)
        {
            Console.WriteLine(fileInfo.FullName);
        }
    }
    

    不仅代码更简单、更健壮且独立于平台。它还使所有其他文件属性(大小、修改时间、权限、所有权)都可以通过RemoteFileInfo class 轻松获得。

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

    (我是 WinSCP 的作者)

    【讨论】:

    • 谢谢你的回答,是的
    猜你喜欢
    • 1970-01-01
    • 2014-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-15
    相关资源
    最近更新 更多