如何判断FTP目录是否存在

本文关键字:是否 存在 FTP 何判断 判断 | 更新日期: 2023-09-27 18:13:08

我编写了以下代码来检测目录是否存在。DirectoryExists方法接受完全限定路径或相对路径。

public bool DirectoryExists(string directory)
{
    try
    {
        FtpWebRequest request = GetRequest(directory);
        request.Method = WebRequestMethods.Ftp.ListDirectory;
        using (FtpWebResponse response = request.GetResponse() as FtpWebResponse)
        using (StreamReader sr = new StreamReader(response.GetResponseStream(), System.Text.Encoding.ASCII))
        {
            sr.ReadToEnd();
        }
        return true;
    }
    catch { }
    return false;
}
protected FtpWebRequest GetRequest(string filename = "")
{
    FtpWebRequest request = WebRequest.Create(_host.GetUrl(filename)) as FtpWebRequest;
    request.Credentials = new NetworkCredential(Username, Password);
    request.Proxy = null;
    request.KeepAlive = false;
    return request;
}

注:_host.GetUrl(filename)返回指定目录或文件名的完全限定路径。在我的例子中,这是ftp://www.mydomain.com/Articles/controls/precisely-defining-kilobytes-megabytes-and-gigabytes

这段代码已经工作了好几个月了。但是突然间它停止工作了。现在,当目录不存在时,在DirectoryExists中不会引发异常。sr.ReadToEnd()只是返回一个空字符串。

我发布了一个类似的问题,有人建议我应该总是把/附加到我的路径的末尾。我尝试了一下,并认为我得到了一个异常,但它现在没有引发异常。

我不知道我正在通信的FTP服务器上的行为是否发生了变化。同样,当我写它的时候,它工作得很好,现在它不工作了。

如何判断FTP目录是否存在?

编辑:

检查调用ReadToEnd()后的响应,我看到:

BannerMessage="220 Microsoft FTP Service'r'n"

ContentLength = 1

ExitMessage ="221再见。' r ' n"

StatusCode = ClosingData

StatusDescription="226传输完成。'r'n"

WelcomeMessage="230用户已登录。'r'n"

更新:

最终,我发现大多数人都在推荐我最初所做的变化。这为汉斯•帕桑特(Hans Passant)提出的问题在于服务器的建议增加了份量。我试图让他们看看这个,但他们似乎对整个讨论有点困惑。我知道他们用的是微软的服务器,我怀疑我能否从他们那里得到一个解决方案。

如果所有这些都失败了,我认为答案是做一个父目录的清单,这确实需要一些额外的工作来处理一些情况,比如当有问题的目录是根目录时,以及当父目录不存在时。

如何判断FTP目录是否存在

FTP服务器在请求一个不存在的目录/文件时返回550消息。这个550在。net中被转换成一个异常。

关于你展示的代码,我看不出在生产中使用StreamReader的理由。一个简单的修改如下:

public bool DirectoryExists(string directory)
{
  try
  {
    FtpWebRequest request = GetRequest(directory);
    request.Method = WebRequestMethods.Ftp.ListDirectory;
    return request.GetResponse() != null;
  }
  catch
  {
    return false;
  }
}

我保留了异常处理(缺失),但我建议你对它进行处理,因为有许多不同的情况需要捕获,与ftp响应无关。

如果目录不存在,

request.GetResponse()将生成一个异常。

我尝试用以下路径获得真正的返回:

  • ftp://ftp.mozilla.org/
  • ftp://ftp.mozilla.org/pub/
  • ftp://ftp.mozilla.org/pub/data/
  • ftp://ftp.mozilla.org/pub/data/bloat-reports/

最后一个是已存在的空目录

ftp://ftp.mozilla.org/pub/data/bloat-reports2/返回false

关于尾随/in路径有一个很大的but

mozilla.org是pub目录下的零字节长度文件

ftp://ftp.mozilla.org/pub/mozilla.org返回true

ftp://ftp.mozilla.org/pub/mozilla.org/返回false,然后返回true ?????

这个行为看起来像你所描述的。您可以很容易地在浏览器上复制它。我建议您对自己的路径执行同样的操作,并检查目录的内容。如果您确实有空文件,请删除它们或将其内容替换为空格,最后检查您的代码以确保您不会创建新文件或以零字节长度重新创建它们。

我希望这对你有帮助。

没有消息,坏消息!我想以上这些对你都没有帮助。也许在你的路径上向上一层就能解决问题。其思想是获取父目录的列表并检查子目录的名称。如果父路径是有效的,它应该总是返回非空字符串。代码如下:

static bool DirectoryExists(string directory)
{
    try
    {
        directory = GetRequest(directory);
        string
            parent = directory.Substring(0, directory.TrimEnd('/').LastIndexOf('/') + 1),
            child = directory.Substring(directory.TrimEnd('/').LastIndexOf('/') + 1).TrimEnd('/');
        FtpWebRequest request = GetRequest(parent);
        request.Method = WebRequestMethods.Ftp.ListDirectory;
        using (FtpWebResponse response = request.GetResponse() as FtpWebResponse)
        {
            if (response == null)
                return false;
            string data = new StreamReader(response.GetResponseStream(), true).ReadToEnd();
            return data.IndexOf(child, StringComparison.InvariantCultureIgnoreCase) >= 0;
        }
    }
    catch
    {
        return false;
    }
}

正如你所看到的,没有必要担心后面的斜杠。

警告:该代码将不涵盖在同一路径下具有相同名称的子目录和文件名的情况。

可能是因为您的服务器上安装了FTP服务器软件。

否则,您可能需要查看响应。查看StatusCode是否有提示

http://msdn.microsoft.com/en-us/library/system.net.ftpstatuscode (v = vs.110) . aspx

最后,如果所有这些都不起作用,试着在那个不存在的目录上写一个哑文本文件

我有类似的代码,通过FTP将项目部署到IIS 6/Windows 2003服务器。在我把它指向IIS7/Windows 2008服务器之前,这工作得很好。我开始看到和你一模一样的行为。我对它进行了调试,并最终将代码更改为以下内容。这是我的代码的直接片段。如果您愿意,我可以包括它调用的方法的源代码,但我认为您理解了这些操作。

try
{
    //Get a recursive FTP Listing
    items = GetFtpListing(target, true);
}
catch(WebException e)
{
    if (string.Equals(e.Message, "The remote server returned an error: (550) File unavailable (e.g., file not found, no access)."))
    {
        CreateRemoteDirectory(target);
        items = GetFtpListing(target, true);
    }
    else
    {
        throw e;
    }
}

GetFtpListing相关部分

List<string> ftpRawList = new List<string>();
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(path);
request.Timeout = 60000;
request.ReadWriteTimeout = 60000;
request.Credentials = this.credentials;
request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
{
    Stream data = response.GetResponseStream();
    using (StreamReader reader = new StreamReader(data))
    {
        string responseString = reader.ReadToEnd();
        ftpRawList.AddRange(responseString.Split(new char[2] { ''r', ''n' }, StringSplitOptions.RemoveEmptyEntries));
    }

我使用下面的命令检查ftp连接凭据是否有效。您可以使用相同的来检查目录是否存在。如果url、用户名和密码正确,则返回true。

URL:你在这里指定你的目录路径。用户:FTP用户名密码:FTP密码


public static bool isValidConnection(string url, string user, string password, ref string errorMessage = "")
{
    try {
        FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
        request.Method = WebRequestMethods.Ftp.ListDirectory;
        request.Credentials = new NetworkCredential(user, password);
        request.KeepAlive = false;
        request.UsePassive = true;
        FtpWebResponse response = (FtpWebResponse)request.GetResponse();
        response.Close();
    } catch (WebException ex) {
        errorMessage = ex.Message;
        return false;
    }
    return true;
}

一种方法是在许多解决方案中列出目录内容,但在我的情况下,我还必须读取数据内容,以便服务器检查目录。如果该目录不存在,则抛出一个webeexception,应该解释该异常以过滤意外错误。

这是我的解决方案:

  bool directoryExists(string path)
    {
        bool? exists = null;

        FtpWebRequest request = (FtpWebRequest)WebRequest.Create(path);
        request.Method = WebRequestMethods.Ftp.ListDirectory;
        request.Credentials = new NetworkCredential("username", "*****");
        FtpWebResponse response = null;
        try
        {
            response = (FtpWebResponse)request.GetResponse();
            using (StreamReader sr = new StreamReader(response.GetResponseStream()))
            {
                string str = sr.ReadLine(); //Just needs to read one line to fire check on server
                sr.Close();
                return true;
            }                                    
        }
        catch (WebException ex)  
        {
            var r = (FtpWebResponse)ex.Response;
            if (r.StatusCode ==
                FtpStatusCode.ActionNotTakenFileUnavailable)
            {
                //Does not exist
                return false;
            }
            throw; //if error is not related to directory existence then the exception needs to be treated above.
        }
        finally
        {
            if (response != null)
                response.Close();
        }
        return false;
    }

我的目标FTP服务器,我知道是一个windows服务器,但我没有访问版本信息。