2010-05-04 7 views
25

Recherche du meilleur moyen de vérifier un répertoire donné via FTP.Comment vérifier si un répertoire FTP existe

i ont actuellement le code suivant:

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

Cela renvoie false si le répertoire est là ou non. Quelqu'un peut me diriger dans la bonne direction.

+0

Il n'est pas recommandé de créer un répertoire pour vérifier s'il existe. Je recommanderais d'utiliser MLST si le serveur supporte la commande (comme FileZilla); Sinon, vous pouvez utiliser CWD, puis la commande LIST. J'ai trouvé cette ressource que je vois, il peut le faire: [Déterminer si un répertoire existe] (http://www.componentpro.com/doc/ftp/Determining-whether-a-directory-exists2.htm) –

Répondre

15

Fondamentalement piégé l'erreur que je reçois lors de la création du répertoire comme ça.

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; 
     } 
    } 
} 
+12

Ce code n'est pas fiable: par exemple si vous n'avez pas de droits d'écriture et qu'il n'y a pas de répertoire désiré, cette fonction retournera vrai. –

+0

Vous pouvez également vérifier la propriété StatusDescription de FtpWebResponse. S'il contient 'exists' (550 Directory existe déjà) alors il existe déjà. ** CEPENDANT ** Je n'ai trouvé aucune spécification ou confirmation que tous les serveurs FTP doivent retourner cela, cela peut être le cas avec FileZilla. Alors testez-le dans votre scénario particulier et décidez si c'est quelque chose que vous voulez faire/risquer. –

0

Accédez au répertoire parent, exécutez la commande "ls" et analysez le résultat.

+0

Puis-je obtenir un exemple? –

-5

Pour ce que cela vaut, vous rendrez la vie de votre FTP un peu plus facile si vous utilisez le composant EnterpriseDT's FTP. C'est gratuit et vous évitera des maux de tête car il traite des commandes et des réponses. Vous travaillez simplement avec un objet sympa et simple.

+1

Downvoted car ce n'est pas gratuit et aussi comme une API Java –

0

Je ne pouvais pas cette suggestion @BillyLogans travailler ....

J'ai trouvé le problème était le répertoire FTP par défaut est/home/usr/fred

Quand je:

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

Je trouve cela se transforme en

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

pour arrêter ce changement dans le répertoire Uri:

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

Ensuite, cela commence à travailler.

6

Je voudrais essayer quelque chose le long de ces lignes:

  • Envoyer MLST < répertoire > commande FTP (définie dans RFC3659) et l'analyse syntaxique est sortie. Il doit renvoyer une ligne valide avec les détails du répertoire pour les répertoires existants.

  • Si la commande MLST n'est pas disponible, essayez de modifier le répertoire de travail dans le répertoire testé en utilisant une commande CWD. N'oubliez pas de déterminer le chemin actuel (commande PWD) avant de passer à un répertoire testé pour pouvoir revenir en arrière.

  • Sur certains serveurs, la combinaison des commandes MDTM et SIZE peut être utilisée à des fins similaires, mais le comportement est assez complexe et hors de portée de cette publication.

Ceci est essentiellement ce que la méthode DirectoryExists dans la version actuelle de notre Rebex FTP component fait. Le code suivant montre comment l'utiliser:

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(); 
+2

Bien que les autres réponses fournissent du code, ils créent essentiellement un nouveau répertoire pour voir si une erreur se produit. Mieux vaut simplement lancer la commande FTP 'CWD' à laquelle le serveur émettra un code de réponse 5xx si le répertoire n'existe pas. – timbo

+0

Merci pour la commande "CWD". –

4

L'utilisateur ce code, il se peut que ce soit votre réponse ..

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

J'ai appelé cette méthode:

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

Pourquoi utiliser une autre bibliothèque - créez votre propre logique de.

+11

Cela retournera uniquement le CWD (Current Working Directory). Quel que soit ce que vous ajoutez à l'adresse de l'hôte (ex: ftp://mondomaine.com) il retournera toujours le répertoire en cours un autre mot IsExists ne sera jamais autre chose que vrai. Si c'est la seule chose que je fais (ci-dessus) alors sur mon serveur il montre simplement "257 '/' est le répertoire courant.". Non "257 '/ abcdir /' est le répertoire courant." comme tout le monde s'y attendrait. –

2

J'ai essayé dans tous les sens pour obtenir un contrôle solide, mais ni les méthodes, ni WebRequestMethods.Ftp.PrintWorkingDirectoryWebRequestMethods.Ftp.ListDirectory fonctionnerait correctement. Ils ont échoué lors de la vérification de ftp://<website>/Logs qui n'existe pas sur le serveur, mais ils le disent. Donc, la méthode que j'ai inventée était d'essayer de télécharger dans le dossier. Cependant, une « chasse aux sorcières » est le format de chemin que vous pouvez lire dans ce fil Uploading to Linux

Voici un extrait de code

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

Je suppose que vous êtes déjà un peu familier avec FtpWebRequest, comme cela est le manière habituelle d'accéder à FTP dans .NET.

Vous pouvez essayer de répertorier le répertoire et de rechercher une erreur StatusCode.

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. 
     } 
    } 
} 
+0

J'ai trouvé cela peu fiable. J'ai un cas où aucune exception n'est levée lorsque le répertoire spécifié n'existe pas. –

7

J'ai également été confronté au même problème. J'utilisais,

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

et j'ai attendu l'exception dans le cas où le répertoire n'existe pas. Cette méthode n'a pas soulevé d'exception. Après quelques essais, j'ai changé le répertoire de "ftp://ftpserver.com/rootdir/test_if_exist_directory" à "ftp://ftpserver.com/rootdir/test_if_exist_directory/". Maintenant, cette pièce travaille pour moi.

Je pense que nous devrions ajouter backslash (/) dans l'uri du dossier ftp pour obtenir ce travail.

Comme demandé, la solution complète sera désormais:

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: 
string ftpDirectory = "ftp://ftpserver.com/rootdir/test_if_exist_directory/"; //Note: backslash at the last position of the path. 
bool dirExists = DoesFtpDirectoryExist(ftpDirectory); 
+0

Ouvrez votre propre question si celle-ci ne résout pas votre problème. Notez également que OP a plus de 4 ans. – gmo

+0

s'il vous plaît essayer votre propre solution et afficher les résultats – Deepend

+1

@ gmo: Cette astuce résolu mon problème complètement. Ce morceau de code se porte bien dans les opérations. – Bikash

-2

La seule façon qui a fonctionné pour moi était une logique inversée en essayant de créer le répertoire/chemin (qui lancera une exception si elle existe déjà) et si oui, supprimez-le à nouveau après. Sinon, utilisez l'exception pour définir un indicateur indiquant que le répertoire/chemin existe. Je suis tout à fait nouveau pour VB.NET et je suis shure il y a une plus belle façon de coder - mais de toute façon voici mon code:

 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 et WebRequestMethods.Ftp.RemoveDirectory sont les méthodes i utilisé pour cela. Toutes les autres solutions n'ont pas fonctionné pour moi.

Espérons que cela aide

Questions connexes