Retrieving creation date of file (FTP)

I'm using the System.Net.FtpWebRequest class and my code is as follows:

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();

This is based off of the examples provided on MSDN but I couldn't find anything more detailed.

I'm storing all the filenames in the folder in names but how can I now iterate through each of those and retrieve their dates? I want to retrieve the dates so I can find the newest files. Thanks.


Solution 1:

This seems to work just fine http://msdn.microsoft.com/en-us/library/system.net.ftpwebresponse.lastmodified(v=VS.90).aspx

FtpWebRequest request = (FtpWebRequest)WebRequest.Create (serverUri);
request.Method = WebRequestMethods.Ftp.GetDateTimestamp;
FtpWebResponse response = (FtpWebResponse)request.GetResponse ();
Console.WriteLine ("{0} {1}",serverUri,response.LastModified);

Solution 2:

Unfortunately, there's no really reliable and efficient way to retrieve timestamps using features offered by .NET framework, as it does not support the FTP MLSD command. The MLSD command provides a listing of remote directory in a standardized machine-readable format. The command and the format is standardized by RFC 3659.

Alternatives you can use, that are supported by .NET framework:

  • ListDirectoryDetails method (the FTP LIST command) to retrieve details of all files in a directory and then you deal with FTP server specific format of the details (*nix format similar to the ls *nix command is the most common, a drawback is that the format may change over time, as for newer files "May 8 17:48" format is used and for older files "Oct 18 2009" format is used).

    DOS/Windows format: C# class to parse WebRequestMethods.Ftp.ListDirectoryDetails FTP response
    *nix format: Parsing FtpWebRequest ListDirectoryDetails line

  • GetDateTimestamp method (the FTP MDTM command) to individually retrieve timestamps for each file. An advantage is that the response is standardized by RFC 3659 to YYYYMMDDHHMMSS[.sss]. A disadvantage is that you have to send a separate request for each file, what can be quite inefficient.

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

Alternatively you can use a 3rd party FTP client implementation that supports the modern MLSD command.

For example WinSCP .NET assembly supports that.

There's even an example for your specific task: Downloading the most recent file.
The example is for PowerShell and the SFTP, but translates to C# and the FTP easily:

// 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();
}

(I'm the author of WinSCP)

Solution 3:

WebRequestMethods.Ftp.ListDirectory returns a "short listing" of all the files in an FTP directory. This type of listing is only going to provide file names - not additional details on the file (like permissions or last modified date).

Use WebRequestMethods.Ftp.ListDirectoryDetails instead. This method will return a long listing of files on the FTP server. Once you've retrieved this list into the names variable, you can split the names variable into an array based on an end of line character. This will result in each array element being a file (or directory) name listing that includes the permissions, last modified date owner, etc...

At this point, you can iterate over this array, examine the last modified date for each file, and decide whether to download the file.

I hope this helps!!