如何在C#中获取FTP近期上传文件并触发通知?
这个问题确实挺棘手的——依赖文件最后修改时间判断新增文件,碰到那些本身修改时间是旧的文件就完全失效了。我结合自己的实战经验给你几个可行的解决思路:
方案1:利用FTP服务器的MLSD命令获取文件上传时间
很多现代FTP服务器(比如IIS、vsftpd)支持MLSD命令,该命令返回的文件信息里通常包含上传/创建时间字段(区别于文件本身的修改时间)。你可以通过FtpWebRequest发送这个命令并解析结果:
var request = (FtpWebRequest)WebRequest.Create("ftp://your-ftp-server/target-path"); request.Method = WebRequestMethods.Ftp.ListDirectoryDetails; request.Credentials = new NetworkCredential("your-username", "your-password"); using (var response = (FtpWebResponse)request.GetResponse()) using (var reader = new StreamReader(response.GetResponseStream())) { string line; while ((line = reader.ReadLine()) != null) { // MLSD返回格式示例:modify=20240520143000;perm=adfrw;size=4096; example.txt if (line.Contains("modify=") && !string.IsNullOrEmpty(line.Split(';').Last())) { var timeSegment = line.Split(';').First(p => p.StartsWith("modify=")).Split('=')[1]; if (DateTime.TryParseExact(timeSegment, "yyyyMMddHHmmss", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime uploadTime)) { if (uploadTime >= DateTime.Now.AddMinutes(-5)) { var fileName = line.Split(';').Last().Trim(); // 触发新增文件通知逻辑 Console.WriteLine($"检测到近期上传文件:{fileName}"); } } } } }
注意:不同FTP服务器的MLSD返回格式可能略有差异,需要根据实际返回内容调整解析逻辑。如果服务器不支持MLSD,这个方法无法使用。
方案2:用WinSCP跟踪文件列表变化(最推荐)
你已经在使用WinSCP,其实它的.NET Assembly内置了文件变更对比功能——通过记录上次扫描的文件列表,下次对比时直接找出新增文件,完全不依赖文件本身的修改时间:
SessionOptions sessionOptions = new SessionOptions { Protocol = Protocol.Ftp, HostName = "your-ftp-server", UserName = "your-username", Password = "your-password" }; // 用于存储上次扫描的文件列表(可持久化到本地文件/数据库,避免程序重启后丢失) Dictionary<string, DateTime> lastScannedFiles = new Dictionary<string, DateTime>(); using (Session session = new Session()) { session.Open(sessionOptions); // 初始化第一次扫描的文件列表 var initialDir = session.ListDirectory("/target-path"); foreach (var file in initialDir.Files) { if (!file.IsDirectory) { lastScannedFiles[file.Name] = file.LastWriteTime; } } // 定时扫描(示例为每5分钟一次) while (true) { Thread.Sleep(TimeSpan.FromMinutes(5)); var currentDir = session.ListDirectory("/target-path"); var currentFiles = currentDir.Files.Where(f => !f.IsDirectory).ToDictionary(f => f.Name, f => f.LastWriteTime); // 找出新增文件:当前列表有但上次列表没有的文件 var newFiles = currentFiles.Keys.Except(lastScannedFiles.Keys); foreach (var fileName in newFiles) { // 触发通知逻辑 Console.WriteLine($"检测到新增文件:{fileName}"); } // 更新扫描记录 lastScannedFiles = currentFiles; } }
这个方案的优势是兼容性强,WinSCP会自动处理不同FTP服务器的差异,而且彻底解决了文件修改时间不准确的问题,上手成本也低(因为你已经熟悉WinSCP)。
方案3:读取FTP服务器的上传日志
如果你的FTP服务器允许开启上传日志(比如IIS的FTP日志、vsftpd的xferlog),可以让服务器记录每次上传操作的详细信息(包括文件名、上传时间、客户端信息等)。你的C#程序可以定期读取日志文件,解析出近期的上传记录来识别新增文件。
这个方法需要你有服务器配置权限,好处是能精准获取上传时间,但需要维护日志的读取和解析逻辑,还要考虑日志滚动、权限等问题。
方案4:修改FTP服务器的上传逻辑(仅限自有服务器)
如果FTP服务器是你自己管理的,可以在服务器端添加脚本(Windows批处理/Linux Shell脚本),当文件上传完成后,强制将文件的最后修改时间更新为当前上传时间。这样你原来基于修改时间的检测逻辑就能正常工作了。
内容的提问来源于stack exchange,提问作者Narendra Jangir

