2014-11-13 3 views
3

Я пытаюсь создать программу, которая будет рекурсивно удалять все файлы и папки с определенного FTP-пути. Моя программа работает хорошо, если в заданном пути есть только несколько файлов или каталогов. По какой-то причине, хотя, если в каталоге несколько файлов, оно просто зависает на линии ReadLine() и в итоге получает ошибку ввода-вывода. Вот мой код:Рекурсивно удалять все файлы и папки с определенного FTP-пути

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

И это мой простой класс контейнер FileObject:

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

Ваши вызовы .Close() являются избыточными с помощью блока 'using'. IDisposable.Dispose() позаботится об этом для каждого из этих методов (если не будет ошибки, о которой я не знаю). –

+0

Попробуйте включить трассировку http://msdn.microsoft.com/en-us/library/bw00b1dc(v=vs.110).aspx и http://msdn.microsoft.com/en-us/library/hyb3xww8(v = vs.110) .aspx Также попробуйте –

+0

@EricJ. - Я пошел вперед и удалил вызовы метода Close(). Это не исправить мою проблему, но вы правы в том, что они не нужны. – Icemanind

ответ

3

Мой вопрос, как представляется, фиксируется с помощью активного режима, а не пассивный. Я добавил это к своему коду:

request.UsePassive = false; 

Это, похоже, исправляет мою проблему. Я тестировал его на большой партии файлов с большим количеством подкаталогов и под-подкаталогов, и теперь он работает безупречно.

Смежные вопросы