我有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);
答案 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);
}
}
}
}
}