C # класс для анализа WebRequestMethods.Ftp.ListDirectoryDetails FTP-ответ - PullRequest
20 голосов
/ 15 августа 2011

Я создаю службу для отслеживания местоположений FTP на наличие новых обновлений и требую возможности проанализировать ответ, полученный от ответа FtpWebRequest , с использованием метода WebRequestMethods.Ftp.ListDirectoryDetails . Было бы довольно легко, если бы все ответы следовали одному и тому же формату, но разное программное обеспечение FTP-сервера предоставляло разные форматы ответов.

Например, можно вернуть:

08-10-11  12:02PM       <DIR>          Version2
06-25-09  02:41PM            144700153 image34.gif
06-25-09  02:51PM            144700153 updates.txt
11-04-10  02:45PM            144700214 digger.tif

И другой сервер может вернуть:

d--x--x--x    2 ftp      ftp          4096 Mar 07  2002 bin
-rw-r--r--    1 ftp      ftp        659450 Jun 15 05:07 TEST.TXT
-rw-r--r--    1 ftp      ftp      101786380 Sep 08  2008 TEST03-05.TXT
drwxrwxr-x    2 ftp      ftp          4096 May 06 12:24 dropoff

И другие различия наблюдались также, поэтому, вероятно, будет ряд тонких различий, с которыми я еще не сталкивался.

Кто-нибудь знает о полностью управляемом (не требующем доступа к внешней dll в Windows) классе C #, который легко обрабатывает эти ситуации?

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

Заранее спасибо за любые предложения, Gavin

Ответы [ 4 ]

9 голосов
/ 29 сентября 2016

Для первого (DOS / Windows) перечисления этот код будет делать:

FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://ftp.example.com/");
request.Credentials = new NetworkCredential("user", "password");
request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream());

string pattern = @"^(\d+-\d+-\d+\s+\d+:\d+(?:AM|PM))\s+(<DIR>|\d+)\s+(.+)$";
Regex regex = new Regex(pattern);
IFormatProvider culture = CultureInfo.GetCultureInfo("en-us");
while (!reader.EndOfStream)
{
    string line = reader.ReadLine();
    Match match = regex.Match(line);
    DateTime modified =
       DateTime.ParseExact(
           match.Groups[1].Value, "MM-dd-yy  hh:mmtt", culture, DateTimeStyles.None);
    long size = (match.Groups[2].Value != "<DIR>") ? long.Parse(match.Groups[2].Value) : 0;
    string name = match.Groups[3].Value;

    Console.WriteLine(
        "{0,-16} size = {1,9}  modified = {2}",
        name, size, modified.ToString("yyyy-MM-dd HH:mm"));
}

Вы получите:

Version2         size =         0  modified = 2011-08-10 12:02
image34.gif      size = 144700153  modified = 2009-06-25 14:41
updates.txt      size = 144700153  modified = 2009-06-25 14:51
digger.tif       size = 144700214  modified = 2010-11-04 14:45

О другом (* nix) листинге см. мой ответ на разбор строки FtpWebRequest ListDirectoryDetails .


Но на самом деле попытка разобрать список, возвращаемый ListDirectoryDetails, не является правильным способом.

Вы хотите использовать FTP-клиент, который поддерживает современную команду MLSD, которая возвращает список каталогов в машиночитаемом формате, указанном в RFC 3659 . Анализ читабельного человеком формата, возвращаемого древней командой LIST (используемой внутри FtpWebRequest для ее метода ListDirectoryDetails), следует использовать в качестве крайней возможности при обращении к устаревшим FTP-серверам, которые не поддерживают MLSD (например, FTP-сервер Microsoft IIS).


Например, WinSCP .NET сборка , вы можете использовать методы Session.ListDirectory или Session.EnumerateRemoteFiles.

Они внутренне используют команду MLSD, но могут использовать команду LIST и поддерживают десятки различных читабельных форматов списков.

Возвращенный список представлен как коллекция RemoteFileInfo экземпляров со свойствами, такими как:

  • Name
  • LastWriteTime (с правильным часовым поясом)
  • Length
  • FilePermissions (разбито на индивидуальные права)
  • Group
  • Owner
  • IsDirectory
  • IsParentDirectory
  • IsThisDirectory

(я автор WinSCP)


Большинство других сторонних библиотек будут делать то же самое. Использование FtpWebRequest класса не является надежным для этой цели. К сожалению, в .NET Framework нет другого встроенного FTP-клиента.

7 голосов
/ 19 ноября 2013

Я столкнулся с той же проблемой и создал простое (хотя и не очень надежное) решение с использованием регулярных выражений для анализа соответствующей информации из каждой строки с помощью групп захвата:

public static Regex FtpListDirectoryDetailsRegex = new Regex(@".*(?<month>(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec))\s*(?<day>[0-9]*)\s*(?<yearTime>([0-9]|:)*)\s*(?<fileName>.*)", RegexOptions.Compiled | RegexOptions.IgnoreCase);

Затем вы можетеИзвлеките значения из групп захвата следующим образом:

        string ftpResponse = "-r--r--r-- 1 ftp ftp              0 Nov 19 11:08 aaa.txt";
        Match match = FtpListDirectoryDetailsRegex.Match(ftpResponse);
        string month = match.Groups["month"].Value;
        string day = match.Groups["day"].Value;
        string yearTime = match.Groups["yearTime"].Value;
        string fileName = match.Groups["fileName"].Value;

Некоторые вещи, которые не обратите внимание:

  • , это будет работать только для ответов каталога с форматом, описанным в ftpResponse переменная выше.В моем случае мне повезло, что я каждый раз обращаюсь к одному и тому же FTP-серверу, поэтому маловероятно, что формат ответа изменится.
  • переменная yearTime может представлять ЛИБО год или времявременная метка файла.Вам нужно будет проанализировать это вручную, ища экземпляр символа двоеточие: символ, который будет указывать, что эта группа захвата содержит время, а не год
4 голосов
/ 15 августа 2011

Одно решение, с которым я столкнулся, это EdtFTPnet

EdtFTPnet представляется довольно функциональным решением, которое обрабатывает множество различных параметров FTP, поэтому идеально.

Это бесплатное решение с открытым исходным кодом, которое я использовал для http://www.ftp2rss.com (небольшой инструмент, который мне был нужен сам, но подумал, что может быть полезен и для других).

0 голосов
/ 19 августа 2011

Взгляните на FTP-клиент Ftp.dll .

Включает автоматический синтаксический анализатор списка каталогов для большинства FTP-серверов на платформах Windows, Unix и Netware.

Обратите внимание, что это коммерческий продукт, который я разработал.

...