C# класс для анализа WebRequestMethods.Ftp.ListDirectoryDetails FTP-ответ

Я создаю службу для отслеживания местоположений 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#, который легко обрабатывает эти ситуации?

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

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

4 ответа

Решение

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

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

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

Для первого (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) списка, см. Мой ответ на строку Parsing FtpWebRequest ListDirectoryDetails.


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

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


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

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

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

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

(Я автор WinSCP)


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

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

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 переменная может представлять ЛИБО год или время метки времени файла. Вам нужно будет проанализировать это вручную, ища экземпляр символа двоеточие: символ, который будет указывать, что эта группа захвата содержит время, а не год

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

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

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

Другие вопросы по тегам