FileSystemWatcher for FTP

2019-03-15 13:07发布

How can I implement a FileSystemWatcher for an FTP location (in C#). The idea is whenever anything gets added in the FTP location I wish to copy it to my local machine. Any ideas will be helpful.

This is a follow up of my previous question Selective FTP download using .NET.

7条回答
倾城 Initia
2楼-- · 2019-03-15 14:05

You cannot use the FileSystemWatcher or any other way, because the FTP protocol does not have any API to notify a client about changes in the remote directory.

All you can do is to periodically iterate the remote tree and find changes.

It's actually rather easy to implement, if you use an FTP client library that supports recursive listing of a remote tree. Unfortunately, the built-in .NET FTP client, the FtpWebRequest does not. But for example with WinSCP .NET assembly version 5.9 (or newer), you can use the Session.EnumerateRemoteFiles method.

See the article Watching for changes in SFTP/FTP server:

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

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

    List<string> prevFiles = null;

    while (true)
    {
        // Collect file list
        List<string> files =
            session.EnumerateRemoteFiles(
                "/remote/path", "*.*", EnumerationOptions.AllDirectories)
            .Select(fileInfo => fileInfo.FullName)
            .ToList();
        if (prevFiles == null)
        {
            // In the first round, just print number of files found
            Console.WriteLine("Found {0} files", files.Count);
        }
        else
        {
            // Then look for differences against the previous list
            IEnumerable<string> added = files.Except(prevFiles);
            if (added.Any())
            {
                Console.WriteLine("Added files:");
                foreach (string path in added)
                {
                    Console.WriteLine(path);
                }
            }

            IEnumerable<string> removed = prevFiles.Except(files);
            if (removed.Any())
            {
                Console.WriteLine("Removed files:");
                foreach (string path in removed)
                {
                    Console.WriteLine(path);
                }
            }
        }

        prevFiles = files;

        Console.WriteLine("Sleeping 10s...");
        Thread.Sleep(10000);
    }
}

(I'm the author of WinSCP)


Though, if you actually want to just download the changes, it's a way easier. Just use the Session.SynchronizeDirectories in the loop.

session.SynchronizeDirectories(
    SynchronizationMode.Local, "/remote/path", @"C:\local\path", true).Check();

If you do not want to use a 3rd party library, you have to do with limitations of the FtpWebRequest. For an example how to recursively list a remote directory tree with the FtpWebRequest, see my answer to C# Download all files and subdirectories through FTP.

查看更多
登录 后发表回答