2011-08-15 16 views
19

Estoy creando un servicio para monitorear ubicaciones FTP para las nuevas actualizaciones y requieren la capacidad de analizar la respuesta de regresar de una respuesta FtpWebRequest utilizando los WebRequestMethods.Ftp.ListDirectoryDetails método. Sería bastante fácil si todas las respuestas siguieran el mismo formato, pero diferentes programas de servidor FTP ofrecen diferentes formatos de respuesta.C# clase para analizar la respuesta WebRequestMethods.Ftp.ListDirectoryDetails FTP

Por ejemplo se podría volver:

08-10-11 12:02PM  <DIR>   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 devolver:

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 se han observado otras diferencias también por lo que no es probable que sea una serie de diferencias sutiles no he me encontré todavía.

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

Solo necesito enumerar el contenido de un directorio con los siguientes detalles: Nombre del archivo/directorio, fecha y hora actualizadas, nombre del archivo/directorio.

Gracias de antemano por cualquier sugerencia, Gavin

+2

Solo una nota: FTP no especifica el formato exacto de la lista, y existen más de 400 formatos (aunque solo dos que ha enumerado, Windows y Unix) se utilizan sobre todo. –

+1

¡Uf, eso es un montón de formatos! – Gavin

+1

Encontré este ejemplo, pero dudo que sea demasiado robusto - http://blogs.msdn.com/b/adarshk/archive/2004/09/15/230177.aspx – Gavin

Respuesta

4

Una solución que se encontró es EdtFTPnet

edtFTPnet Parece que hay una solución con multitud de funciones que maneja una gran cantidad de diferentes opciones de FTP lo que es ideal.

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

0

Eche un vistazo a Ftp.dll FTP client.

Incluye automatic directory listing parser 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é.

+0

Saludos Pawel, muy apreciado. Se mantendrá la versión gratuita de EdtFTPnet por ahora a menos que encuentre algunos límites con su versión gratuita. – Gavin

4

estoy frente a este mismo problema y han construido una solución simple (aunque no muy robusta), utilizando una expresión regular para analizar la información relevante de cada línea usando grupos de captura:

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

A continuación, puede extraer los valores fuera de los grupos de captura por:

 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; 

hay cosas que no tenga en cuenta 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.Usted tendrá que analizar de forma manual mediante la búsqueda de una instancia de colon: carácter que le permita indicar que este grupo de captura contiene una vez más que el año
+0

¡Funciona genial! –

6

Por primera (DOS/Windows) lista este código va a hacer :

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+(<DIR>|\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 != "<DIR>") ? 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")); 
} 

Usted recibirá:

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 

Por el otro listado (* nix), ver my answer to Parsing FtpWebRequest ListDirectoryDetails line.


Pero, en realidad tratando de analizar la lista devuelta por el ListDirectoryDetails no es el camino correcto a seguir.

Desea utilizar un cliente FTP que admita el comando MLSD moderno que devuelve un listado de directorios en un formato legible por máquina especificado en el RFC 3659. Analizar el formato de fácil lectura que devuelve la antigua LIST comando (utilizado internamente por el FtpWebRequest por su método de ListDirectoryDetails) debe ser utilizado como la opción de último recurso, cuando se habla de servidores FTP obsoletos, que no son compatibles con el comando MLSD (como el Microsoft Servidor FTP de IIS).


Por ejemplo, con WinSCP .NET assembly, puede utilizar sus Session.ListDirectory o Session.EnumerateRemoteFiles métodos.

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

El listado devuelto se presenta como colección de RemoteFileInfo instances con propiedades como:

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

(yo soy el autor de WinSCP)


mayoría de las otras bibliotecas 3 ª parte harán lo mismo. El uso del FtpWebRequest class no es confiable para este propósito. Desafortunadamente, no hay otro cliente FTP incorporado en .NET Framework.

+0

Gracias por compartir. ¿Puedo preguntar, cómo lo haces en WinSCP? – c00000fd

+0

@ c00000fd ¿Qué? Lista de directorio? Ver https://winscp.net/eng/docs/library_session_listdirectory#example –

Cuestiones relacionadas