【问题标题】:How to check if an FTP directory exists如何检查FTP目录是否存在
【发布时间】:2011-02-15 16:23:27
【问题描述】:

寻找通过 FTP 检查给定目录的最佳方式。

目前我有以下代码:

private bool FtpDirectoryExists(string directory, string username, string password)
{

    try
    {
        var request = (FtpWebRequest)WebRequest.Create(directory);
        request.Credentials = new NetworkCredential(username, password);
        request.Method = WebRequestMethods.Ftp.GetDateTimestamp;

        FtpWebResponse response = (FtpWebResponse)request.GetResponse();
    }
    catch (WebException ex)
    {
        FtpWebResponse response = (FtpWebResponse)ex.Response;
        if (response.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
            return false;
        else
            return true;
    }
    return true;
}

无论目录是否存在,这都会返回 false。有人能指出我正确的方向吗?

【问题讨论】:

    标签: c# .net ftp ftpwebrequest


    【解决方案1】:

    导航到父目录,执行“ls”命令,解析结果。

    【讨论】:

    • 但是如果父目录不存在,则返回错误状态550。
    【解决方案2】:

    不管怎样,如果您使用EnterpriseDT's FTP 组件,您的 FTP 生活会轻松很多。它是免费的,因为它处理命令和响应,所以可以省去你的麻烦。您只需处理一个漂亮、简单的对象。

    【讨论】:

    • 我不会加入反对票,因为自原始帖子以来情况可能已经发生变化,但该组件不再免费。
    【解决方案3】:

    基本上捕获了像这样创建目录时收到的错误。

    private bool CreateFTPDirectory(string directory) {
    
        try
        {
            //create the directory
            FtpWebRequest requestDir = (FtpWebRequest)FtpWebRequest.Create(new Uri(directory));
            requestDir.Method = WebRequestMethods.Ftp.MakeDirectory;
            requestDir.Credentials = new NetworkCredential("username", "password");
            requestDir.UsePassive = true;
            requestDir.UseBinary = true;
            requestDir.KeepAlive = false;
            FtpWebResponse response = (FtpWebResponse)requestDir.GetResponse();
            Stream ftpStream = response.GetResponseStream();
    
            ftpStream.Close();
            response.Close();
    
            return true;
        }
        catch (WebException ex)
        {
            FtpWebResponse response = (FtpWebResponse)ex.Response;
            if (response.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
            {
                response.Close();
                return true;
            }
            else
            {
                response.Close();
                return false;
            }  
        }
    }
    

    【讨论】:

    • 此代码不可靠:例如,如果您没有写入权限并且没有所需的目录,此函数将返回 true。
    • 还有检查 FtpWebResponse 的 StatusDescription 属性的选项。如果它包含“存在”(550 目录已经存在),那么它已经存在。 但是我还没有找到任何规范或保证所有 FTP 服务器都必须返回它,FileZilla 可能就是这种情况。因此,请在您的特定场景中对其进行测试,并确定它是否是您想做/冒险的事情。
    【解决方案4】:

    我无法让这个@BillyLogans 的建议起作用......

    我发现问题在于默认的 FTP 目录是 /home/usr/fred

    当我使用时:

    String directory = "ftp://some.domain.com/mydirectory"
    FtpWebRequest requestDir = (FtpWebRequest)FtpWebRequest.Create(new Uri(directory));
    

    我发现这变成了

    "ftp:/some.domain.com/home/usr/fred/mydirectory"
    

    要停止此操作,请将 Uri 目录更改为:

    String directory = "ftp://some.domain.com//mydirectory"
    

    然后这开始工作了。

    【解决方案5】:

    我会尝试这样的方式:

    • 发送 MLST FTP 命令(在 RFC3659 中定义)并解析它的输出。它应该返回包含现有目录详细信息的有效行。

    • 如果 MLST 命令不可用,请尝试使用 CWD 命令将工作目录更改为测试目录。在切换到测试目录之前不要忘记确定当前路径(PWD 命令)以便能够返回。

    • 在某些服务器上,MDTM 和 SIZE 命令的组合可用于类似目的,但行为相当复杂,超出了本文的范围。

    这基本上就是我们Rebex FTP component 的当前版本中的 DirectoryExists 方法所做的。下面的代码展示了如何使用它:

    string path = "/path/to/directory";
    
    Rebex.Net.Ftp ftp = new Rebex.Net.Ftp();
    ftp.Connect("hostname");
    ftp.Login("username","password");
    
    Console.WriteLine(
      "Directory '{0}' exists: {1}", 
      path, 
      ftp.DirectoryExists(path)
    );
    
    ftp.Disconnect();
    

    【讨论】:

    • 虽然其他答案提供了代码,但它们本质上是在创建一个新目录以查看是否发生错误。如果目录不存在,最好简单地发出 FTP 'CWD' 命令,服务器将发出 5xx 回复代码。
    【解决方案6】:

    使用此代码可能是您的答案..

     public bool FtpDirectoryExists(string directoryPath, string ftpUser, string ftpPassword)
            {
                bool IsExists = true;
                try
                {
                    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(directoryPath);
                    request.Credentials = new NetworkCredential(ftpUser, ftpPassword);
                    request.Method = WebRequestMethods.Ftp.PrintWorkingDirectory;
    
                    FtpWebResponse response = (FtpWebResponse)request.GetResponse();
                }
                catch (WebException ex)
                {
                    IsExists = false;
                }
                return IsExists;
            }
    

    我称这个方法为:

    bool result =    FtpActions.Default.FtpDirectoryExists( @"ftp://mydomain.com/abcdir", txtUsername.Text, txtPassword.Text);
    

    为什么要使用另一个库 - 创建您自己的逻辑。

    【讨论】:

    • 这只会返回 CWD(当前工作目录)。无论您将什么附加到主机地址(例如:mydomain.com),它都将始终返回当前目录,换句话说,IsExists 永远不会是真的。如果这是我唯一要做的事情(上面),那么在我的服务器上它只会显示“257'/'是当前目录。”。不是“257 '/abcdir/' 是当前目录。”正如每个人所期望的那样。
    【解决方案7】:

    我尝试了各种方法来获得可靠的检查,但 WebRequestMethods.Ftp.PrintWorkingDirectoryWebRequestMethods.Ftp.ListDirectory 方法都不能正常工作。他们在检查服务器上不存在但他们说存在的ftp://<website>/Logs 时失败了。

    所以我想出的方法是尝试上传到文件夹。但是,一个“陷阱”是您可以在此线程 Uploading to Linux 中阅读的路径格式

    这是一个代码sn-p

    private bool DirectoryExists(string d) 
    { 
        bool exists = true; 
        try 
        { 
            string file = "directoryexists.test"; 
            string path = url + homepath + d + "/" + file;
            //eg ftp://website//home/directory1/directoryexists.test
            //Note the double space before the home is not a mistake
    
            //Try to save to the directory 
            req = (FtpWebRequest)WebRequest.Create(path); 
            req.ConnectionGroupName = "conngroup1"; 
            req.Method = WebRequestMethods.Ftp.UploadFile; 
            if (nc != null) req.Credentials = nc; 
            if (cbSSL.Checked) req.EnableSsl = true; 
            req.Timeout = 10000; 
    
            byte[] fileContents = System.Text.Encoding.Unicode.GetBytes("SAFE TO DELETE"); 
            req.ContentLength = fileContents.Length; 
    
            Stream s = req.GetRequestStream(); 
            s.Write(fileContents, 0, fileContents.Length); 
            s.Close(); 
    
            //Delete file if successful 
            req = (FtpWebRequest)WebRequest.Create(path); 
            req.ConnectionGroupName = "conngroup1"; 
            req.Method = WebRequestMethods.Ftp.DeleteFile; 
            if (nc != null) req.Credentials = nc; 
            if (cbSSL.Checked) req.EnableSsl = true; 
            req.Timeout = 10000; 
    
            res = (FtpWebResponse)req.GetResponse(); 
            res.Close(); 
        } 
        catch (WebException ex) 
        { 
            exists = false; 
        } 
        return exists; 
    } 
    

    【讨论】:

      【解决方案8】:

      我假设您已经对 FtpWebRequest 有所熟悉,因为这是在 .NET 中访问 FTP 的常用方法。

      您可以尝试列出目录并检查错误状态代码。

      try 
      {  
          FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://ftp.microsoft.com/12345");  
          request.Method = WebRequestMethods.Ftp.ListDirectory;  
          using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())  
          {  
              // Okay.  
          }  
      }  
      catch (WebException ex)  
      {  
          if (ex.Response != null)  
          {  
              FtpWebResponse response = (FtpWebResponse)ex.Response;  
              if (response.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)  
              {  
                  // Directory not found.  
              }  
          }  
      } 
      

      【讨论】:

      【解决方案9】:

      我也遇到了类似的问题。我正在使用,

      FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://ftpserver.com/rootdir/test_if_exist_directory");  
      request.Method = WebRequestMethods.Ftp.ListDirectory;  
      FtpWebResponse response = (FtpWebResponse)request.GetResponse();
      

      并等待异常,以防目录不存在。这个方法没有抛出异常。

      经过几次尝试和尝试,我将目录更改为: “ftp://ftpserver.com/rootdir/test_if_exist_directory”到:“ftp://ftpserver.com/rootdir/test_if_exist_directory/”。现在代码对我有用。

      我认为我们应该将正斜杠 (/) 附加到 ftp 文件夹的 URI 以使其工作。

      根据要求,现在完整的解决方案是:

      public bool DoesFtpDirectoryExist(string dirPath)
      {
          try
          {
              FtpWebRequest request = (FtpWebRequest)WebRequest.Create(dirPath);  
              request.Method = WebRequestMethods.Ftp.ListDirectory;  
              FtpWebResponse response = (FtpWebResponse)request.GetResponse();
              return true;
           }
           catch(WebException ex)
           {
               return false;
           }
      }
      
      //Calling the method (note the forwardslash at the end of the path):
      string ftpDirectory = "ftp://ftpserver.com/rootdir/test_if_exist_directory/";
      bool dirExists = DoesFtpDirectoryExist(ftpDirectory);
      

      【讨论】:

      【解决方案10】:

      对我有用的唯一方法是通过尝试创建目录/路径(如果它已经存在将引发异常)并在之后再次删除它来实现逆向逻辑。否则,使用 Exception 设置一个标志,表示目录/路径存在。我对 VB.NET 很陌生,我确信有更好的方法来编写这个 - 但无论如何这是我的代码:

              Public Function DirectoryExists(directory As String) As Boolean
              ' Reversed Logic to check if a Directory exists on FTP-Server by creating the Directory/Path
              ' which will throw an exception if the Directory already exists. Otherwise create and delete the Directory
      
              ' Adjust Paths
              Dim path As String
              If directory.Contains("/") Then
                  path = AdjustDir(directory)     'ensure that path starts with a slash
              Else
                  path = directory
              End If
      
              ' Set URI (formatted as ftp://host.xxx/path)
      
              Dim URI As String = Me.Hostname & path
      
              Dim response As FtpWebResponse
      
              Dim DirExists As Boolean = False
              Try
                  Dim request As FtpWebRequest = DirectCast(WebRequest.Create(URI), FtpWebRequest)
                  request.Credentials = Me.GetCredentials
                  'Create Directory - if it exists WebException will be thrown
                  request.Method = WebRequestMethods.Ftp.MakeDirectory
      
                  'Delete Directory again - if above request did not throw an exception
                  response = DirectCast(request.GetResponse(), FtpWebResponse)
                  request = DirectCast(WebRequest.Create(URI), FtpWebRequest)
                  request.Credentials = Me.GetCredentials
                  request.Method = WebRequestMethods.Ftp.RemoveDirectory
                  response = DirectCast(request.GetResponse(), FtpWebResponse)
                  DirExists = False
      
              Catch ex As WebException
                  DirExists = True
              End Try
              Return DirExists
      
          End Function
      

      WebRequestMethods.Ftp.MakeDirectory 和 WebRequestMethods.Ftp.RemoveDirectory 是我用于此的方法。所有其他解决方案都不适合我。

      希望对你有帮助

      【讨论】:

        【解决方案11】:

        这是我最好的。从父目录获取列表,并检查父目录是否有正确的子名称

        public void TryConnectFtp(string ftpPath)
                {
                    string[] splited = ftpPath.Split('/');
                    StringBuilder stb = new StringBuilder();
                    for (int i = 0; i < splited.Length - 1; i++)
                    {
                        stb.Append(splited[i] +'/');
                    }
                    string parent = stb.ToString();
                    string child = splited.Last();
        
                    FtpWebRequest testConnect = (FtpWebRequest)WebRequest.Create(parent);
                    testConnect.Method = WebRequestMethods.Ftp.ListDirectory;
                    testConnect.Credentials = credentials;
                    using (FtpWebResponse resFtp = (FtpWebResponse)testConnect.GetResponse())
                    {
                        StreamReader reader = new StreamReader(resFtp.GetResponseStream());
                        string result = reader.ReadToEnd();
                        if (!result.Contains(child) ) throw new Exception("@@@");
        
                        resFtp.Close();
                    }
                }
        

        【讨论】:

          猜你喜欢
          • 2013-05-19
          • 2023-03-09
          • 1970-01-01
          • 2020-06-07
          • 2013-01-16
          • 1970-01-01
          • 1970-01-01
          • 2015-01-29
          • 2012-09-12
          相关资源
          最近更新 更多