【问题标题】:How to recursively delete a folder with the files within using FtpWebRequest?如何使用 FtpWebRequest 递归删除包含文件的文件夹?
【发布时间】:2011-06-19 12:20:42
【问题描述】:

我想删除 FTP 中的一个文件夹,它是递归的文件。

我可以实现任何示例代码吗?

【问题讨论】:

标签: c# ftp ftpwebrequest


【解决方案1】:

首先,您必须列出目录中的所有文件:

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

那你需要一个删除单个文件的方法(因为只有空文件夹才能删除):

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

最后:

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

你可以很容易地这样调用它(对我来说,这些方法在一个名为“Ftp”的类中):

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

当然,您需要自定义这些行,但它对我来说非常有效:)

【讨论】:

    【解决方案2】:

    FtpWebRequest class(或 .NET 框架中的任何其他 FTP 实现)不支持递归操作。您必须自己实现递归:

    • 列出远程目录
    • 迭代条目、删除文件并递归到子目录(再次列出它们等)

    棘手的部分是从子目录中识别文件。使用FtpWebRequest 无法以便携的方式做到这一点。不幸的是,FtpWebRequest 不支持MLSD 命令,这是在 FTP 协议中检索具有文件属性的目录列表的唯一可移植方式。另见Checking if object on FTP server is file or directory

    您的选择是:

    • 对文件名执行操作,该操作对于文件肯定会失败,而对于目录肯定会成功(反之亦然)。 IE。您可以尝试下载“名称”。如果成功,它是一个文件,如果失败,它是一个目录。但是,当您有大量条目时,这可能会成为性能问题。
    • 您可能很幸运,在您的特定情况下,您可以通过文件名来区分目录中的文件(即,您的所有文件都有扩展名,而子目录没有)
    • 您使用长目录列表(LIST 命令 = ListDirectoryDetails 方法)并尝试解析特定于服务器的列表。许多 FTP 服务器使用 *nix 样式的列表,您可以在其中通过条目开头的 d 标识目录。但是许多服务器使用不同的格式。以下示例使用这种方法(假设为 *nix 格式)。
    • 在这种特定情况下,您可以尝试将条目作为文件删除。如果删除失败,请尝试将条目列为目录。如果列表成功,您假设它是一个文件夹并相应地继续。不幸的是,当您尝试列出文件时,某些服务器不会出错。他们只会返回一个包含单个文件条目的列表。
    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 应该类似于 ftp://example.com/directory/to/delete/


    或者使用支持递归操作的 3rd 方库。

    例如使用WinSCP .NET assembly,您只需调用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();
    } 
    

    如果服务器支持,WinSCP 在内部使用MLSD 命令。如果没有,它使用LIST 命令并支持数十种不同的列表格式。

    (我是 WinSCP 的作者)

    【讨论】:

      【解决方案3】:

      你可以在这里找到很好的小例子:

      http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.aspx

      在示例中,他们使用WebRequestMethods.Ftp.UploadFile 类来指导他们想做什么样的操作。

      一旦您拥有要删除的父目录的句柄,就使用 WebRequestMethods.Ftp.RemoveDirectory 方法:

      http://msdn.microsoft.com/en-us/library/system.net.webrequestmethods.ftp.aspx

      【讨论】:

        【解决方案4】:

        没有一个解决方案真正适用于不同类型的服务器,除了使用 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;
                        }
                    }
        
                }
            }
        

        【讨论】:

          猜你喜欢
          • 2020-02-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-01-31
          • 2011-01-15
          • 2013-03-20
          • 2012-11-19
          • 1970-01-01
          相关资源
          最近更新 更多