Recursively delete all files and folders from a specific FTP path

I am trying to create a program that will recursively delete all files and folders from a specific FTP path. My program works well if there are only a few files or directories in the given path. For some reason, even though there are multiple files in the directory, it just hangs at the line ReadLine()

and ends up getting an I / O error. Here is my code:

class Program
{
    private const string FtpSite = "myftpsite.com";
    private const string FtpUserName = "myusername";
    private const string FtpPassword = "mypassword";

    static void Main(string[] args)
    {
        DeleteFilesAndFolders("/");
    }

    private static void DeleteFilesAndFolders(string path)
    {
        if (path != null && (path.StartsWith(@"\\") || path.StartsWith("//")))
            path = path.Remove(0, 1);
        List<FileObject> files = DirectoryListing(path);

        foreach (FileObject file in files.Where(file => !file.IsDirectory))
        {
            DeleteFile(path, file.FileName);
        }

        foreach (FileObject file in files.Where(file => file.IsDirectory))
        {
            DeleteFilesAndFolders(path + "/" + file.FileName);
            DeleteFolder(path + "/" + file.FileName);
        }
    }

    private static void DeleteFile(string path, string file)
    {
        var clsRequest = (FtpWebRequest)WebRequest.Create("ftp://" + FtpSite + path + "/" + file);
        clsRequest.Credentials = new NetworkCredential(FtpUserName, FtpPassword);

        clsRequest.Method = WebRequestMethods.Ftp.DeleteFile;

        using (var response = (FtpWebResponse) clsRequest.GetResponse())
        {
            using (Stream datastream = response.GetResponseStream())
            {
                if (datastream == null)
                    return;
                using (var sr = new StreamReader(datastream))
                {
                    sr.ReadToEnd();
                    sr.Close();
                }
                datastream.Close();
                response.Close();
            }
        }
    }

    private static void DeleteFolder(string path)
    {
        var clsRequest = (FtpWebRequest)WebRequest.Create("ftp://" + FtpSite + path);
        clsRequest.Credentials = new NetworkCredential(FtpUserName, FtpPassword);

        clsRequest.Method = WebRequestMethods.Ftp.RemoveDirectory;

        using (var response = (FtpWebResponse)clsRequest.GetResponse())
        {
            using (Stream datastream = response.GetResponseStream())
            {
                if (datastream == null)
                    return;
                using (var sr = new StreamReader(datastream))
                {
                    sr.ReadToEnd();
                    sr.Close();
                }
                datastream.Close();
                response.Close();
            }
        }
    }

    private static List<FileObject> DirectoryListing(string path)
    {
        var regex = new Regex(@"^([d-])([rwxt-]{3}){3}\s+\d{1,}\s+.*?(\d{1,})\s+(\w+\s+\d{1,2}\s+(?:\d{4})?)(\d{1,2}:\d{2})?\s+(.+?)\s?$",
            RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
        var request = (FtpWebRequest)WebRequest.Create("ftp://" + FtpSite + path);
        request.Credentials = new NetworkCredential(FtpUserName, FtpPassword);
        request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;

        var result = new List<FileObject>();

        using (var response = (FtpWebResponse) request.GetResponse())
        {
            using (Stream responseStream = response.GetResponseStream())
            {
                if (responseStream == null)
                    return null;
                using (var reader = new StreamReader(responseStream))
                {
                    while (!reader.EndOfStream)
                    {
                        string r = reader.ReadLine();
                        if (string.IsNullOrWhiteSpace(r))
                            continue;
                        var reg = regex.Match(r);
                        var c = new FileObject
                        {
                            FileName = reg.Groups[6].Value,
                            IsDirectory = reg.Groups[1].Value.ToLower() == "d"
                        };
                        result.Add(c);
                    }
                    reader.Close();
                }
                response.Close();
            }
        }

        return result;
    }
}

      

And this is my simple container of the FileObject class:

internal class FileObject
{
    public bool IsDirectory { get; set; }
    public string FileName { get; set; }
}

      

+3


source to share


1 answer


My problem seems to have been fixed by using active mode instead of passive. I added this to my code:

request.UsePassive = false;

      



This seems to fix my problem. I tested it on a large part of files with a lot of subdirectories and subdirectories and it works flawlessly now.

+3


source







All Articles