如何使用uribuilder获取目录下的所有子目录

How to get all sub directories under a directory using uribuilder

正在尝试创建一个 UriBuilder 来列出所有子目录供以后使用。

我已针对此过程尝试了 Microsoft 的示例,并尝试使用 directory.getdirectory 方法但没有成功。

String result = String.Empty;
Search searchResults = new Search();

try
{
    UriBuilder uriBuilder = new UriBuilder();
    uriBuilder.Scheme = "ftp";
    uriBuilder.Host = "ftp.myfilepath.com/public/doc";
    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(uriBuilder.Uri);

    request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;

    FtpWebResponse response = (FtpWebResponse)request.GetResponse();

    Stream responseStream = response.GetResponseStream();
    StreamReader reader = new StreamReader(responseStream);
    Console.WriteLine(reader.ReadToEnd());

    Console.WriteLine($"Directory List Complete, status {response.StatusDescription}");

    reader.Close();
    response.Close();
    result = reader.ReadToEnd();

    if (result != null)
    {
        searchResults.Messages = result;
    }
}
catch (Exception ex)
{
    searchResults.Messages = "File not found.";
} 

我希望它列出在 UriBuilder 给出的路径下找到的目录。结果总是空的,我不明白为什么或我错过了什么。

问题

忽略一些语法错误(第 18 行和第 22 行缺少关键字 var 或类型声明),您的代码运行正常。唯一的问题是你调用了 reader.ReadToEnd() 两次,而且,第二次调用是在你明确关闭 ResponseStreamStreamReader.

之后

第一个调用在第 12 行,它将目录列表打印到控制台:

Console.WriteLine(reader.ReadToEnd());

第二次调用在第 18 行,您试图将其 return 值放入变量 result:

result = reader.ReadToEnd();

但就在您关闭 ResponseStreamStreamReader 之后:

reader.Close();
response.Close();
result = reader.ReadToEnd();

所以你甚至会收到一条错误消息,解释你做错了什么:

Cannot read from a closed TextReader.

第18行抛出异常

即使您将对 Close() 方法的两次调用都移动到第 18 行之后,它也不会起作用,因为对 reader.ReadToEnd() 方法的第一次调用会清空读取缓冲区并释放NetworkStream 对象,所以第 18 行会抛出以下异常:

Cannot access a disposed object. Object name: 'System.Net.Sockets.NetworkStream'.

解决方案

您需要做的是只调用方法 reader.ReadToEnd() 一次,在关闭 ResponseStreamStreamReader 并存储其 return 之前执行此操作变量中的值。然后,你可以对结果做任何你想做的事情:

var uriBuilder = new UriBuilder();
uriBuilder.Scheme = "ftp";
uriBuilder.Host = "ftp.myfilepath.com/public/doc";
var request = (FtpWebRequest)WebRequest.Create(uriBuilder.Uri);

request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;

var response = (FtpWebResponse)request.GetResponse();

var responseStream = response.GetResponseStream();
var reader = new StreamReader(responseStream);
var result = reader.ReadToEnd();

Console.WriteLine(result);
Console.WriteLine($"Directory List Complete, status {response.StatusDescription}");

reader.Close();
response.Close();

工作示例

如果您完全按照建议执行所有操作,则以下代码必须有效:

  1. 在 Visual Studio 中创建一个包含控制台应用程序项目的新解决方案,使用 .NET Framework 4.7.2
  2. 将以下代码放入Program.cs:

    using System;
    using System.IO;
    using System.Net;
    
    namespace FtpDirectoryListing
    {
        class Program
        {
            static void Main(string[] args)
            {
                var uriBuilder = new UriBuilder();
                uriBuilder.Scheme = "ftp";
                uriBuilder.Host = "speedtest.tele2.net";
                var request = (FtpWebRequest)WebRequest.Create(uriBuilder.Uri);
    
                request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
    
                var response = (FtpWebResponse)request.GetResponse();
    
                var responseStream = response.GetResponseStream();
                var reader = new StreamReader(responseStream);
                var result = reader.ReadToEnd();
    
                Console.WriteLine(result);
                Console.WriteLine($"Directory List Complete, status {response.StatusDescription}");
    
                reader.Close();
                response.Close();
            }
        }
    }
    
  3. 运行这

  4. 与我们分享它产生的任何潜在错误