web-dev-qa-db-fra.com

Comment vérifier si le fichier existe sur FTP avant FtpWebRequest

J'ai besoin d'utiliser FtpWebRequest pour mettre un fichier dans un répertoire FTP. Avant le téléchargement, je voudrais d'abord savoir si ce fichier existe.

Quelle méthode ou propriété dois-je utiliser pour vérifier si ce fichier existe?

66
Tomasz Smykowski
var request = (FtpWebRequest)WebRequest.Create
    ("ftp://ftp.domain.com/doesntexist.txt");
request.Credentials = new NetworkCredential("user", "pass");
request.Method = WebRequestMethods.Ftp.GetFileSize;

try
{
    FtpWebResponse response = (FtpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
    FtpWebResponse response = (FtpWebResponse)ex.Response;
    if (response.StatusCode ==
        FtpStatusCode.ActionNotTakenFileUnavailable)
    {
        //Does not exist
    }
}

En règle générale, c'est une mauvaise idée d'utiliser des exceptions pour les fonctionnalités de votre code comme ceci, mais dans ce cas, je pense que c'est une victoire pour le pragmatisme. La liste d'appels sur l'annuaire a le potentiel d'être bien plus inefficace que d'utiliser des exceptions de cette manière.

Si vous ne l'êtes pas, sachez que ce n'est pas une bonne pratique!

EDIT: "Ça marche pour moi!"

Cela semble fonctionner sur la plupart des serveurs ftp mais pas sur tous. Certains serveurs nécessitent l'envoi de "TYPE I" avant que la commande SIZE ne fonctionne. On aurait pensé que le problème devait être résolu comme suit:

request.UseBinary = true;

Malheureusement, c'est une limitation de conception (gros gros bogue!) Qu'à moins que FtpWebRequest ne télécharge ou télécharge un fichier, il n'enverra PAS de "TYPE I". Voir discussion et réponse de Microsoft ici .

Je recommanderais d'utiliser la WebRequestMethod suivante à la place, cela fonctionne pour moi sur tous les serveurs que j'ai testés, même ceux qui ne renverraient pas de taille de fichier.

WebRequestMethods.Ftp.GetDateTimestamp
113
user42467

Car

request.Method = WebRequestMethods.Ftp.GetFileSize

peut échouer dans certains cas (550: TAILLE non autorisée en ASCII), vous pouvez simplement vérifier l'horodatage à la place.

reqFTP.Credentials = new NetworkCredential(inf.LogOn, inf.Password);
reqFTP.UseBinary = true;
reqFTP.Method = WebRequestMethods.Ftp.GetDateTimestamp;
8
Nolmë Informatique

FtpWebRequest (ni aucune autre classe dans .NET) n'a pas de méthode explicite pour vérifier l'existence d'un fichier. Vous devez abuser d'une demande comme GetFileSize ou GetDateTimestamp.

string url = "ftp://ftp.example.com/remote/path/file.txt";

WebRequest request = WebRequest.Create(url);
request.Credentials = new NetworkCredential("username", "password");
request.Method = WebRequestMethods.Ftp.GetFileSize;
try
{
    request.GetResponse();
    Console.WriteLine("Exists");
}
catch (WebException e)
{
    FtpWebResponse response = (FtpWebResponse)e.Response;
    if (response.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
    {
        Console.WriteLine("Does not exist");
    }
    else
    {
        Console.WriteLine("Error: " + e.Message);
    }
}

Si vous voulez un code plus simple, utilisez une bibliothèque FTP tierce.

Par exemple, avec WinSCP .NET Assembly , vous pouvez utiliser son Session.FileExists méthode :

SessionOptions sessionOptions = new SessionOptions {
    Protocol = Protocol.Ftp,
    HostName = "ftp.example.com",
    UserName = "username",
    Password = "password",
};

Session session = new Session();
session.Open(sessionOptions);

if (session.FileExists("/remote/path/file.txt"))
{
    Console.WriteLine("Exists");
}
else
{
    Console.WriteLine("Does not exist");
}

(je suis l'auteur de WinSCP)

3
Martin Prikryl