33

寻找通过 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。有人可以指出我正确的方向。

4

11 回答 11

20

基本上捕获了我在创建目录时收到的错误。

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;
        }  
    }
}
于 2010-05-07T21:43:45.490 回答
16

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

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);
于 2014-06-04T21:33:50.367 回答
9

我假设您已经对 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.  
        }  
    }  
} 
于 2012-08-20T16:15:37.230 回答
7

我会尝试这样的事情:

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

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

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

这基本上是我们当前版本的Rebex FTP 组件中的 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();
于 2010-12-17T16:33:37.030 回答
4

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

 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);

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

于 2011-07-20T10:44:58.103 回答
2

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

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

这是一个代码片段

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; 
} 
于 2011-11-02T16:48:13.983 回答
0

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

于 2010-05-04T21:38:46.140 回答
0

我无法让这个@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"

然后这开始工作。

于 2010-09-24T17:04:37.423 回答
-1

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

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();
            }
        }
于 2021-02-05T08:45:24.387 回答
-3

对我有用的唯一方法是通过尝试创建目录/路径(如果它已经存在将引发异常)并在之后再次删除它来实现逆向逻辑。否则,使用 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 是我用于此的方法。所有其他解决方案都不适合我。

希望能帮助到你

于 2016-05-08T18:57:42.993 回答
-5

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

于 2010-05-04T21:48:37.870 回答