Получение даты создания файла (FTP)

Я использую класс System.Net.FtpWebRequest, а мой код выглядит следующим образом:

FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://example.com/folder");
request.Method = WebRequestMethods.Ftp.ListDirectory;

request.Credentials = new NetworkCredential("username", "password");

FtpWebResponse response = (FtpWebResponse)request.GetResponse();

Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);

string names = reader.ReadToEnd();

reader.Close();
response.Close();

Это основано на примерах, представленных в MSDN, но я не смог найти ничего более подробного.

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

Ответы

Ответ 1

WebRequestMethods.Ftp.ListDirectory возвращает "короткий список" всех файлов в каталоге FTP. Этот тип листинга будет содержать только имена файлов, а не дополнительные сведения о файле (например, разрешения или последнюю измененную дату).

Используйте WebRequestMethods.Ftp.ListDirectoryDetails вместо этого. Этот метод вернет длинный список файлов на FTP-сервере. После того как вы извлекли этот список в переменную names, вы можете разбить переменную names на массив на основе символа конца строки. Это приведет к тому, что каждый элемент массива будет списком имен файлов (или каталогов), который включает разрешения, последний измененный владелец даты и т.д.

В этот момент вы можете перебирать этот массив, проверять последнюю измененную дату для каждого файла и решать, загружать ли файл.

Надеюсь, это поможет!

Ответ 3

К сожалению, нет надежного и эффективного способа получения временных меток с использованием функций, предлагаемых платформой.NET, поскольку он не поддерживает команду FTP MLSD. Команда MLSD предоставляет список удаленных каталогов в стандартном машиночитаемом формате. Команда и формат стандартизованы RFC 3659.

Альтернативы, которые вы можете использовать, которые поддерживаются платформой.NET:

  • ListDirectoryDetails (команда FTP LIST) для получения сведений обо всех файлах в каталоге, а затем вы имеете дело с конкретным форматом данных FTP-сервера (формат * nix, аналогичный команде ls * nix, является наиболее распространенным, недостатком является то, что формат может меняться со временем, так как для более старых файлов используется формат "8 мая 17:48", а для более старых файлов используется формат "18 октября 2009").

    Формат DOS/Windows: класс С# для разбора WebRequestMethods.Ftp.ListDirectoryDetails FTP-ответ
    * nix format: Parsing FtpWebRequest ListDirectoryDetails line

  • GetDateTimestamp (команда FTP MDTM) для индивидуального получения временных меток для каждого файла. Преимущество заключается в том, что ответ стандартизован RFC 3659 на YYYYMMDDHHMMSS[.sss]. Недостатком является то, что вам нужно отправить отдельный запрос для каждого файла, что может быть весьма неэффективным.

    const string uri = "ftp://example.com/remote/path/file.txt";
    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(uri);
    request.Method = WebRequestMethods.Ftp.GetDateTimestamp;
    FtpWebResponse response = (FtpWebResponse)request.GetResponse();
    Console.WriteLine("{0} {1}", uri, response.LastModified);
    

В качестве альтернативы вы можете использовать стороннюю реализацию FTP-клиента, которая поддерживает современную команду MLSD.

Например, поддержка WinSCP.NET поддерживает это.

Там даже пример для вашей конкретной задачи: Загрузка самого последнего файла.
Пример для PowerShell и SFTP, но легко переводит на С# и FTP:

// Setup session options
SessionOptions sessionOptions = new SessionOptions
{
    Protocol = Protocol.Ftp,
    HostName = "example.com",
    UserName = "username",
    Password = "password",
};

using (Session session = new Session())
{
    // Connect
    session.Open(sessionOptions);

    // Get list of files in the directory
    string remotePath = "/remote/path/";
    RemoteDirectoryInfo directoryInfo = session.ListDirectory(remotePath);

    // Select the most recent file
    RemoteFileInfo latest =
        directoryInfo.Files
            .OrderByDescending(file => file.LastWriteTime)
            .First();

    // Download the selected file
    string localPath = @"C:\local\path\";
    string sourcePath = RemotePath.EscapeFileMask(remotePath + latest.Name);
    session.GetFiles(sourcePath, localPath).Check();
}

(Я автор WinSCP)

Ответ 4

Сначала вам нужно разбить имена, используя String.Split в разделителе имени файла. Затем перебираем все строки и перемещаем каталоги