为什么 FtpWebRequest return 是这个现有目录的空流?

Why does FtpWebRequest return an empty stream for this existing directory?

我不确定为什么会得到这个结果。我在 Linux 服务器上 运行 这个。 (这是我的小型网站的共享虚拟主机帐户。)

文件分组如下:

并且Another Dir里面有一个文件:

所以我正在尝试检索服务器上不存在的 1somelongdir1234567 目录中 badname 目录的内容,使用以下代码:

try
{
    FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(
        "ftp://server12.some-domain.com/public_html/1somelongdir1234567/badname");
    ftpRequest.EnableSsl = true;
    ftpRequest.Credentials = new NetworkCredential("user", "password");
    ftpRequest.KeepAlive = true;
    ftpRequest.Timeout = -1;

    ftpRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;

    using (FtpWebResponse response1 = (FtpWebResponse)ftpRequest.GetResponse())
    {
        //*****BEGIN OF EDIT*****
        Console.WriteLine(response1.StatusDescription);
        Console.WriteLine(response1.StatusCode);
        //*****END OF EDIT*****

        using (StreamReader streamReader = new StreamReader(response1.GetResponseStream()))
        {
            List<string> arrList = new List<string>();

            for (; ; )
            {
                string line = streamReader.ReadLine();

                //I get to here, where `line` is null????

                if (string.IsNullOrEmpty(line))
                    break;

                arrList.Add(line);

                //*****BEGIN OF EDIT*****
                Console.WriteLine(line);
                //*****END OF EDIT*****
            }
        }
    }
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

如您所见,没有这样的文件夹 badname 但我的 ftpRequest.GetResponse() 没有抛出异常,而是成功,然后 streamReader.ReadLine() returns null就像我在上面的代码中展示的那样。

更奇怪的是,如果我提供这样的实际目录:

    FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(
        "ftp://server12.some-domain.com/public_html/1somelongdir1234567/Another%20Dir");

streamReader.ReadLine()还是returnsnull.

有人可以解释为什么吗?


编辑:好的,伙计们,我更新了上面的代码以检索状态代码。不过我还是很疑惑。

首先,这是连接 URI 的三个值和我得到的 response/output:

示例 1:

//Existing folder
"ftp://server12.some-domain.com/public_html/1somelongdir1234567"

输出:

150 Accepted data connection

OpeningData
drwxr-xr-x    3 username   username         4096 Sep  5 05:51 .
drwxr-x---  118 username   99               4096 Sep  5 05:54 ..
drwxr-xr-x    2 username   username         4096 Sep  5 05:52 Another Dir
-rw-r--r--    1 username   username           11 Sep  5 05:51 test123.txt

示例 2:

//Another existing folder
"ftp://server12.some-domain.com/public_html/1somelongdir1234567/Another%20Dir"

输出:

150 Accepted data connection

OpeningData

示例 3:

//Nonexistent folder
"ftp://server12.some-domain.com/public_html/1somelongdir1234567/SomeBogusName"

输出:

150 Accepted data connection

OpeningData

那么,为什么示例 2 的结果与示例 3 的结果相同?

至于 ftp 服务器是什么,我无法在网络日志和 FtpWebRequest 本身中看到它。这是我从 Microsoft Network Monitor 得到的:

Welcome to Pure-FTPd [privsep] [TLS] ----------..
220-You are user number 4 of 50 allowed... 220-Local time is now 13:14. Server port: 21...
220-This is a private system - No anonymous login..
220-IPv6 connections are also welcome on this server...
220 You will be disconnected after 15 minutes of inactivity...

正如 stuartd 指出的那样,您会在响应中得到一个 FTP 状态代码,据我所知,由于 FTP 命令的工作方式,当服务器无法执行您请求的命令时,您永远不会得到异常。服务器只会通过 FTP 响应代码告诉您失败。

你必须意识到的一件事是 FTP 没有针对它发回的文本的标准 ,因为它从未被设计为机器响应解释。如果您有时间,请查找 the code of FileZilla,并检查他们的 class 以解释文件列表 (directorylistingparser.cpp)。有几十种 种解释方法,应用程序会尝试所有方法,直到找到一种方法。因为,除非您知道要连接的是哪种 FTP,否则这是唯一的方法。

因此,如果您请求一个不存在的目录时该特定服务器决定发回一个空字符串,那么他们的 FTP 实现就是这样做的,而弄清楚这意味着什么是客户的问题。

如果您无法从 FTP 响应代码中找出失败,您可以测试它是否 returns 与 现有但空文件夹。如果是这样,您可以轻松区分那个和这个空响应,并将空响应视为程序中的 "not found" 错误。

ListDirectory/ListDirectoryDetails 方法的 URL 通常应以斜线结尾。

没有斜线,结果往往不确定。

WebRequest.Create("ftp://example.com/public_html/1somelongdir1234567/Another%20Dir/");