Cómo verificar si el archivo existe en FTP antes de FtpWebRequest

Necesito usar FtpWebRequest para poner un archivo en un directorio FTP. Antes de la carga, primero quisiera saber si este archivo existe.

¿Qué método o propiedad debo usar para verificar si este archivo existe?

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

Como regla general, es una mala idea usar Excepciones para la funcionalidad en su código como este, sin embargo, en este caso, creo que es una victoria para el pragmatismo. La lista de llamadas en el directorio tiene el potencial de ser mucho más ineficiente que usar excepciones de esta manera.

Si no lo eres, ¡ten en cuenta que no es una buena práctica!

EDITAR: “¡Funciona para mí!”

Esto parece funcionar en la mayoría de los servidores ftp, pero no en todos. Algunos servidores requieren enviar “TYPE I” antes de que el comando SIZE funcione. Uno hubiera pensado que el problema debería resolverse de la siguiente manera:

 request.UseBinary = true; 

Desafortunadamente, es una limitación de diseño (gran error gordo) que a menos que FtpWebRequest esté descargando o cargando un archivo, NO enviará “TYPE I”. Vea la discusión y la respuesta de Microsoft aquí .

Recomiendo usar el siguiente WebRequestMethod en su lugar, esto funciona para mí en todos los servidores que probé, incluso aquellos que no devolverían un tamaño de archivo.

 WebRequestMethods.Ftp.GetDateTimestamp 

Porque

 request.Method = WebRequestMethods.Ftp.GetFileSize 

puede fallar en algún caso (550: TAMAÑO no permitido en modo ASCII), puede simplemente marcar Marca de tiempo en su lugar.

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

FtpWebRequest (ni ninguna otra clase en .NET) no tiene ningún método explícito para verificar la existencia de un archivo. Necesita abusar de una solicitud como GetFileSize o 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 desea un código más directo, use una biblioteca FTP de terceros.

Por ejemplo, con el ensamblado WinSCP .NET , puede usar su método Session.FileExists :

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

(Soy el autor de WinSCP)

Yo uso FTPStatusCode.FileActionOK para verificar si el archivo existe …

luego, en la sección “else”, devuelve falso.