监视ASP.NET/C#中的FTP目录

时间:2019-03-05 10:50:59

标签: c# .net ftp filesystemwatcher ftpwebrequest

我有FileSystem个监视程序,用于本地目录。一切正常。我希望对FTP实施相同的操作。有什么办法可以实现?我检查了很多解决方案,但不清楚。

逻辑:希望晚于某个时间戳从FTP获取文件。
面临的问题:从FTP获取所有文件,然后过滤结果会影响性能(使用FtpWebRequest)。

有什么正确的方法吗? (WinSCP处于保留状态。现在不能使用它。)

FileSystemWatcher oFsWatcher = new FileSystemWatcher();
OFSWatchers.Add(oFsWatcher);
oFsWatcher.Path = sFilePath;

oFsWatcher.Filter = string.IsNullOrWhiteSpace(sFileFilter) ? "*.*" : sFileFilter;
oFsWatcher.NotifyFilter = NotifyFilters.FileName;

oFsWatcher.EnableRaisingEvents = true;
oFsWatcher.IncludeSubdirectories = bIncludeSubdirectories;
oFsWatcher.Created += new FileSystemEventHandler(OFsWatcher_Created);

3 个答案:

答案 0 :(得分:1)

除非您有权访问托管该服务的操作系统;会有点困难。

FileSystemWatcher在文件系统上放置了一个钩子,一旦有事情发生,它将立即通知您的应用程序。

FTP command specifications没有这种钩子。除此之外,它总是由客户端启动。

因此,要实现这种逻辑,您应该定期执行NLST来列出FTP目录内容并自己跟踪更改(或散列,也许是(MDTM)。

更多信息:

答案 1 :(得分:1)

您不能使用FileSystemWatcher或任何其他方式,因为FTP协议没有任何API可以通知客户端有关远程目录中的更改。

您所能做的就是定期迭代远程树并查找更改。

如果您使用支持递归列出远程树的FTP客户端库,则实际上很容易实现。不幸的是,内置的.NET FTP客户端FtpWebRequest却没有。但是例如对于WinSCP .NET assembly,您可以使用Session.EnumerateRemoteFiles method

请参阅文章Watching for changes in SFTP/FTP server

while (true)
{
    SynchronizationResult result =
        session.SynchronizeDirectories(
            SynchronizationMode.Local, "/remote/path", @"C:\local\path", true);
    result.Check();
    // You can inspect result.Downloads for a list for updated files

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

(我是WinSCP的作者)


但是,如果您实际上只想下载更改,则更容易。只需在循环中使用Session.SynchronizeDirectories

FtpWebRequest

这将甚至更新已修改的文件,而不仅仅是新文件。


尽管从Web应用程序使用WinSCP .NET程序集可能会出现问题。如果您不想使用第三方库,则必须考虑FtpWebRequest的限制。有关如何使用{{1}}递归列出远程目录树的示例,请参阅我对List names of files in FTP directory and its subdirectories的回答。


您已编辑问题,说我建议的解决方案存在性能问题。尽管您已经提出了一个涵盖以下内容的新问题:
Get FTP file details based on datetime in C#

答案 2 :(得分:0)

我有替代解决方案来实现自己的功能。

说明:

我正在使用相同的文件夹结构从FTP(需要读取权限)下载文件。

因此,每次运行作业/服务时,我都可以将相同文件(完整路径)存入物理路径,如果不存在,则可以将其视为新文件。而且Ii可以为此做一些动作,也可以下载。

这只是一个替代解决方案。

代码更改:

 private static void GetFiles()
 {
    using (FtpClient conn = new FtpClient())
    {
        string ftpPath = "ftp://myftp/";

        string downloadFileName = @"C:\temp\FTPTest\";

        downloadFileName +=  "\\";

        conn.Host = ftpPath;
        //conn.Credentials = new NetworkCredential("ftptest", "ftptest");
        conn.Connect();

        //Get all directories

        foreach (FtpListItem item in conn.GetListing(conn.GetWorkingDirectory(),
            FtpListOption.Modify | FtpListOption.Recursive))
        {
            // if this is a file
            if (item.Type == FtpFileSystemObjectType.File)
            {
                string localFilePath = downloadFileName + item.FullName;

                //Only newly created files will be downloaded.
                if (!File.Exists(localFilePath))
                {
                    conn.DownloadFile(localFilePath, item.FullName);
                    //Do any action here.
                    Console.WriteLine(item.FullName);
                }
            }
        }
    }
}