2011-02-01 11 views

Odpowiedz

10

najpierw trzeba wymienić wszystkie pliki w katalogu:

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

Następnie trzeba metodę usunąć pojedynczy plik (bo można usunąć folder tylko jeśli jest pusta):

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

I wreszcie:

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

Można łatwo nazywają to tak (dla mnie te metody są w klasie o nazwie "FTP"):

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

Oczywiście, trzeba dostosować te linie, ale to działało idealnie dla mnie :)

4

Nie ma wsparcia dla operacji rekurencyjnych w FtpWebRequest class (lub jakiejkolwiek innej realizacji FTP w .NET). Trzeba wdrożyć rekursji siebie:

  • Lista zdalny katalog
  • Iterate wpisy, usuwanie plików i podkatalogów w recursing (wymieniając je ponownie, itd.)

Tricky część jest zidentyfikowanie pliki z podkatalogów. Nie ma sposobu, aby zrobić to w sposób przenośny z FtpWebRequest. The FtpWebRequest Niestety nie obsługuje polecenia MLSD, który jest jedynym przenośnym sposobem pobierania listy katalogów z atrybutami plików w protokole FTP. Zobacz także Checking if object on FTP server is file or directory.

wyboru są następujące opcje:

  • Wykonaj operację na nazwę pliku, który jest z pewnością nie do pliku i powodzenia dla katalogu (lub odwrotnie). To znaczy. możesz spróbować pobrać "nazwę". Jeśli to się uda, jest to plik, jeśli się to nie uda, jest to katalog. Ale może to być problem z wydajnością, gdy masz dużą liczbę wpisów.
  • Możesz mieć szczęście iw swoim konkretnym przypadku możesz wskazać plik z katalogu według nazwy pliku (np.wszystkie twoje pliki mają rozszerzenie, a podkatalogi nie).
  • Używasz długiego katalogu (metoda LIST command = ListDirectoryDetails) i próbujesz przeanalizować listę specyficzną dla serwera. Wiele serwerów FTP używa * listy w stylu nix, gdzie identyfikujesz katalog na d na samym początku wpisu. Ale wiele serwerów używa innego formatu. W poniższym przykładzie zastosowano to podejście (zakładając format * nix).
  • W tym konkretnym przypadku możesz po prostu spróbować usunąć wpis jako plik. Jeśli usuwanie nie powiedzie się, spróbuj wpisać pozycję jako katalog. Jeśli aukcja się powiedzie, zakładasz, że jest to folder i postępuj odpowiednio. Niestety niektóre serwery nie zawierają błędów, gdy próbujesz wyświetlić listę plików. Po prostu zwrócą listę z pojedynczym wpisem do pliku.
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(); 
} 

url powinno być jak ftp://example.com/directory/to/delete/


Albo użyć 3rd biblioteki strona, która obsługuje operacje rekurencyjne.

Na przykład z WinSCP .NET assembly można usunąć cały katalog z pojedynczym wywołaniu 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(); 
} 

Wewnętrznie WinSCP używa komendy MLSD, jeśli jest obsługiwane przez serwer. Jeśli nie, używa polecenia LIST i obsługuje wiele różnych formatów aukcji.

(jestem autorem WinSCP)

0

Żadne z rozwiązań naprawdę pracowali nad różnymi typami serwerów z wyjątkiem korzystania 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; 
       } 
      } 

     } 
    } 
Powiązane problemy