Clase C # para analizar WebRequestMethods.Ftp.ListDirectoryDetails Respuesta de FTP

Estoy creando un servicio para supervisar ubicaciones de FTP para nuevas actualizaciones y necesito analizar la respuesta devuelta desde una respuesta de FtpWebRequest utilizando el método WebRequestMethods.Ftp.ListDirectoryDetails . Sería bastante fácil si todas las respuestas siguieran el mismo formato, pero diferentes progtwigs de servidor FTP ofrecen diferentes formatos de respuesta.

Por ejemplo, uno podría regresar:

08-10-11 12:02PM  Version2 06-25-09 02:41PM 144700153 image34.gif 06-25-09 02:51PM 144700153 updates.txt 11-04-10 02:45PM 144700214 digger.tif 

Y otro servidor podría regresar:

 d--x--x--x 2 ftp ftp 4096 Mar 07 2002 bin -rw-r--r-- 1 ftp ftp 659450 Jun 15 05:07 TEST.TXT -rw-r--r-- 1 ftp ftp 101786380 Sep 08 2008 TEST03-05.TXT drwxrwxr-x 2 ftp ftp 4096 May 06 12:24 dropoff 

Y también se han observado otras diferencias, por lo que es probable que haya una serie de diferencias sutiles que aún no he encontrado.

¿Alguien sabe de una clase C # completamente administrada (no requiere acceso a dll externo en Windows) que maneja estas situaciones sin problemas?

Solo necesito enumerar los contenidos de un directorio con los siguientes detalles: nombre del archivo / directorio, fecha y hora actualizadas o creadas por última vez, nombre del archivo / directorio.

Gracias de antemano por cualquier sugerencia, Gavin

Para el primer listado (DOS / Windows), este código hará:

 FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://ftp.example.com/"); request.Credentials = new NetworkCredential("user", "password"); request.Method = WebRequestMethods.Ftp.ListDirectoryDetails; StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream()); string pattern = @"^(\d+-\d+-\d+\s+\d+:\d+(?:AM|PM))\s+(|\d+)\s+(.+)$"; Regex regex = new Regex(pattern); IFormatProvider culture = CultureInfo.GetCultureInfo("en-us"); while (!reader.EndOfStream) { string line = reader.ReadLine(); Match match = regex.Match(line); DateTime modified = DateTime.ParseExact( match.Groups[1].Value, "MM-dd-yy hh:mmtt", culture, DateTimeStyles.None); long size = (match.Groups[2].Value != "") ? long.Parse(match.Groups[2].Value) : 0; string name = match.Groups[3].Value; Console.WriteLine( "{0,-16} size = {1,9} modified = {2}", name, size, modified.ToString("yyyy-MM-dd HH:mm")); } 

Conseguirás:

 Version2 size = 0 modified = 2011-08-10 12:02 image34.gif size = 144700153 modified = 2009-06-25 14:41 updates.txt size = 144700153 modified = 2009-06-25 14:51 digger.tif size = 144700214 modified = 2010-11-04 14:45 

Para la otra lista (* nix), vea mi respuesta a la línea de FtpWebRequest ListDirectoryDetails .


Pero, en realidad, intentar analizar la lista devuelta por ListDirectoryDetails no es el camino correcto.

Desea utilizar un cliente FTP que admita el moderno comando MLSD que devuelve una lista de directorios en un formato legible por máquina especificado en el RFC 3659 . El análisis del formato legible por humanos devuelto por el antiguo comando LIST (utilizado internamente por FtpWebRequest para su método ListDirectoryDetails ) debe utilizarse como la opción de último recurso, cuando se habla con servidores FTP obsoletos, que no admiten el comando MLSD (como Microsoft Servidor FTP de IIS).


Por ejemplo, con el ensamblado WinSCP .NET , puede usar sus métodos Session.ListDirectory o Session.EnumerateRemoteFiles .

Usan internamente el comando MLSD , pero pueden recurrir al comando LIST y admiten docenas de diferentes formatos de listas legibles por humanos.

La lista devuelta se presenta como una colección de instancias de RemoteFileInfo con propiedades como:

  • Name
  • LastWriteTime (con la zona horaria correcta)
  • Length
  • FilePermissions (analizado en derechos individuales)
  • Group
  • Owner
  • IsDirectory
  • IsParentDirectory
  • IsThisDirectory

(Soy el autor de WinSCP)


La mayoría de las otras bibliotecas de terceros harán lo mismo. El uso de la clase FtpWebRequest no es confiable para este propósito. Desafortunadamente, no hay otro cliente FTP incorporado en .NET Framework.

Estoy enfrentando el mismo problema y he construido una solución simple (aunque no muy robusta) usando un Regex para analizar la información relevante de cada línea usando grupos de captura:

 public static Regex FtpListDirectoryDetailsRegex = new Regex(@".*(?(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec))\s*(?[0-9]*)\s*(?([0-9]|:)*)\s*(?.*)", RegexOptions.Compiled | RegexOptions.IgnoreCase); 

A continuación, puede extraer los valores de los grupos de captura de la siguiente manera:

  string ftpResponse = "-r--r--r-- 1 ftp ftp 0 Nov 19 11:08 aaa.txt"; Match match = FtpListDirectoryDetailsRegex.Match(ftpResponse); string month = match.Groups["month"].Value; string day = match.Groups["day"].Value; string yearTime = match.Groups["yearTime"].Value; string fileName = match.Groups["fileName"].Value; 

Algunas cosas que no se mencionan son:

  • esto solo funcionará para respuestas de directorio con el formato descrito que se encuentra en la variable ftpResponse anterior. En mi caso, tengo la suerte de que solo accedo al mismo servidor FTP cada vez, por lo que es poco probable que el formato de respuesta cambie.
  • la variable yearTime puede representar YA SEA el año o la hora de la marca de tiempo del archivo. Necesitará analizar esto manualmente al buscar una instancia de los dos puntos: carácter que indicará que este grupo de captura contiene un tiempo en lugar de un año

Una solución que encontré es EdtFTPnet

EdtFTPnet parece ser una solución completa que maneja muchas opciones de FTP diferentes, por lo que es ideal.

Es la solución gratuita de código abierto que he utilizado para http://www.ftp2rss.com (una pequeña herramienta que necesitaba pero que también podría ser útil para otros).

Eche un vistazo al cliente de FTP http://Ftp.dll .

Incluye un analizador automático de listado de directorios para la mayoría de los servidores FTP en plataformas Windows, Unix y Netware.

Tenga en cuenta que este es un producto comercial que desarrollé.