2011-02-01 18 views

Respuesta

10

primer lugar hay que enumerar todos los archivos en el directorio:

public static List<string> DirectoryListing(string Path, string ServerAdress, string Login, string Password) 
    { 
     FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://" + ServerAdress + Path); 
     request.Credentials = new NetworkCredential(Login, Password); 

     request.Method = WebRequestMethods.Ftp.ListDirectory;    

     FtpWebResponse response = (FtpWebResponse)request.GetResponse(); 
     Stream responseStream = response.GetResponseStream(); 
     StreamReader reader = new StreamReader(responseStream); 

     List<string> result = new List<string>(); 

     while (!reader.EndOfStream) 
     { 
      result.Add(reader.ReadLine()); 
     } 

     reader.Close(); 
     response.Close(); 

     return result; 
    } 

Luego hay un método para eliminar un solo archivo (porque se puede eliminar una carpeta solamente si está vacío):

public static void DeleteFTPFile(string Path, string ServerAdress, string Login, string Password) 
    { 
     FtpWebRequest clsRequest = (System.Net.FtpWebRequest)WebRequest.Create("ftp://" + ServerAdress + Path); 
     clsRequest.Credentials = new System.Net.NetworkCredential(Login, Password); 

     clsRequest.Method = WebRequestMethods.Ftp.DeleteFile; 

     string result = string.Empty; 
     FtpWebResponse response = (FtpWebResponse)clsRequest.GetResponse(); 
     long size = response.ContentLength; 
     Stream datastream = response.GetResponseStream(); 
     StreamReader sr = new StreamReader(datastream); 
     result = sr.ReadToEnd(); 
     sr.Close(); 
     datastream.Close(); 
     response.Close(); 
    } 

Y, por último:

public static void DeleteFTPDirectory(string Path, string ServerAdress, string Login, string Password) 
{ 
     FtpWebRequest clsRequest = (System.Net.FtpWebRequest)WebRequest.Create("ftp://" + ServerAdress + Path); 
     clsRequest.Credentials = new System.Net.NetworkCredential(Login, Password); 

     List<string> filesList = DirectoryListing(Path, ServerAdress, Login, Password); 

     foreach (string file in filesList) 
     { 
      DeleteFTPFile(Path + file, ServerAdress, Login, Password); 
     } 

     clsRequest.Method = WebRequestMethods.Ftp.RemoveDirectory; 

     string result = string.Empty; 
     FtpWebResponse response = (FtpWebResponse)clsRequest.GetResponse(); 
     long size = response.ContentLength; 
     Stream datastream = response.GetResponseStream(); 
     StreamReader sr = new StreamReader(datastream); 
     result = sr.ReadToEnd(); 
     sr.Close(); 
     datastream.Close(); 
     response.Close(); 
    } 

se le puede llamar fácilmente esto como que (para mí esos métodos están en una clase llamada "ftp"):

Ftp.DeleteFTPDirectory (the_path_of_your_folder_in_ftp, your_server_address, your_ftp_login, your_ftp_password);

Por supuesto, tendrá que personalizar esas líneas, pero funcionó perfectamente para mí :)

4

No hay apoyo para las operaciones recursivas de la FtpWebRequest class (o cualquier otra aplicación FTP en el marco .NET). Usted tiene que poner en práctica la recursividad a sí mismo:

  • Lista el directorio remoto
  • Iterar las entradas, borrar archivos y recursiva en subdirectorios (enumerarlos de nuevo, etc.)

parte difícil es identificar archivos de subdirectorios. No hay forma de hacerlo de una manera portátil con el FtpWebRequest. Desafortunadamente, el FtpWebRequest no es compatible con el comando MLSD, que es la única forma portátil de recuperar la lista de directorios con atributos de archivos en el protocolo FTP. Vea también Checking if object on FTP server is file or directory.

Las opciones son:

  • realizar una operación en un nombre de archivo que es seguro que no para un archivo y para tener éxito para el directorio (o viceversa). Es decir. puedes intentar descargar el "nombre". Si eso tiene éxito, es un archivo, si eso falla, es un directorio. Pero eso puede convertirse en un problema de rendimiento, cuando tienes una gran cantidad de entradas.
  • Puede tener suerte y, en su caso específico, puede distinguir un archivo de un directorio por un nombre de archivo (es decir,todos sus archivos tienen una extensión, mientras que los subdirectorios no)
  • Utilice una lista larga de directorios (LIST command = ListDirectoryDetails method) e intente analizar una lista específica del servidor. Muchos servidores FTP usan la lista * nix-style, donde identifica un directorio por el d al principio de la entrada. Pero muchos servidores usan un formato diferente. El siguiente ejemplo usa este enfoque (asumiendo el formato * nix).
  • En este caso específico, puede intentar eliminar la entrada como un archivo. Si la eliminación falla, intente listar la entrada como un directorio. Si el listado tiene éxito, suponga que es una carpeta y proceda en consecuencia. Lamentablemente, algunos servidores no generan errores cuando intenta listar un archivo. Simplemente devolverán una lista con una sola entrada para el archivo.
static void DeleteFtpDirectory(string url, NetworkCredential credentials) 
{ 
    FtpWebRequest listRequest = (FtpWebRequest)WebRequest.Create(url); 
    listRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails; 
    listRequest.Credentials = credentials; 

    List<string> lines = new List<string>(); 

    using (FtpWebResponse listResponse = (FtpWebResponse)listRequest.GetResponse()) 
    using (Stream listStream = listResponse.GetResponseStream()) 
    using (StreamReader listReader = new StreamReader(listStream)) 
    { 
     while (!listReader.EndOfStream) 
     { 
      lines.Add(listReader.ReadLine()); 
     } 
    } 

    foreach (string line in lines) 
    { 
     string[] tokens = 
      line.Split(new[] { ' ' }, 9, StringSplitOptions.RemoveEmptyEntries); 
     string name = tokens[8]; 
     string permissions = tokens[0]; 

     string fileUrl = url + name; 

     if (permissions[0] == 'd') 
     { 
      DeleteFtpDirectory(fileUrl + "/", credentials); 
     } 
     else 
     { 
      FtpWebRequest deleteRequest = (FtpWebRequest)WebRequest.Create(fileUrl); 
      deleteRequest.Method = WebRequestMethods.Ftp.DeleteFile; 
      deleteRequest.Credentials = credentials; 

      deleteRequest.GetResponse(); 
     } 
    } 

    FtpWebRequest removeRequest = (FtpWebRequest)WebRequest.Create(url); 
    removeRequest.Method = WebRequestMethods.Ftp.RemoveDirectory; 
    removeRequest.Credentials = credentials; 

    removeRequest.GetResponse(); 
} 

El url debería ser como ftp://example.com/directory/to/delete/


o utilizar una biblioteca de 3 ª parte que soporta las operaciones recursivas.

Por ejemplo, con WinSCP .NET assembly puede eliminar directorio completo con una sola llamada a Session.RemoveFiles:

// Setup session options 
SessionOptions sessionOptions = new SessionOptions 
{ 
    Protocol = Protocol.Ftp, 
    HostName = "example.com", 
    UserName = "user", 
    Password = "mypassword", 
}; 

using (Session session = new Session()) 
{ 
    // Connect 
    session.Open(sessionOptions); 

    // Delete folder 
    session.RemoveFiles("/home/user/foldertoremove").Check(); 
} 

Internamente, WinSCP utiliza el comando MLSD, si es compatible con el servidor. De lo contrario, usa el comando LIST y admite docenas de formatos de listado diferentes.

(yo soy el autor de WinSCP)

0

Ninguna de las soluciones realmente trabajado en diferentes tipos de servidores, excepto usando System.Net.FtpClient

using System.Net.FtpClient; 
static void DeleteFtpDirectoryAndContent(string host, string path, NetworkCredential credentials, string dontDeleteFileUrl) 
    { 
     using (FtpClient conn = new FtpClient()) 
     { 
      conn.Host = host; 
      conn.Credentials = credentials; 

      foreach (FtpListItem item in conn.GetListing(path, FtpListOption.AllFiles | FtpListOption.ForceList)) 
      { 

       switch (item.Type) 
       { 
        case FtpFileSystemObjectType.Directory: 
         conn.DeleteDirectory(item.FullName, true, FtpListOption.AllFiles | FtpListOption.ForceList); 
         break; 
        case FtpFileSystemObjectType.File: 
         if (!dontDeleteFileUrl.EndsWith(item.FullName, StringComparison.InvariantCultureIgnoreCase)) 
          conn.DeleteFile(item.FullName); 
         break; 
       } 
      } 

     } 
    } 
Cuestiones relacionadas