使用ListDirectoryDetails获取FTP文件时文件名缺失及条目异常问题
解决FTP目录列表返回异常:条目多余+文件名缺失问题
看起来你在用C#的FtpWebRequest获取FTP目录文件时踩了个常见的坑——返回的列表不仅多了两个条目,前两个还出现了文件名缺失的情况,我来帮你拆解问题根源,再给你针对性的解决方案:
问题到底出在哪?
首先得明确:你用的ListDirectoryDetails方法,返回的是带完整文件属性的目录列表(类似你在终端敲ls -l或者Windows里用dir命令的输出),不是单纯的文件名列表。这就导致两个核心问题:
- 多出的两个条目:FTP服务器默认会在目录列表里返回
.(当前目录)和..(上级目录)这两个导航用的特殊项,这就是你看到数组多了2个条目的原因。 - 文件名缺失:你直接把每一行完整内容存进列表,但这些行里包含了权限、修改时间、文件大小等元数据,不是纯文件名。而前两行刚好是
.和..,它们的“文件名”就是.和..,如果你的后续处理逻辑是提取文件名,可能会误判成“缺失”。
两种解决方案任你选
方案1:直接获取纯文件名列表(最简单)
如果你不需要文件权限、大小这些元数据,直接把请求方法改成ListDirectory就行——这个方法返回的就是干净的文件名列表,不会包含.、..,也没有额外的属性信息:
public static string[] GetFilesInDirectory(string requestUriString, string username, string password) { var lines = new List<string>(); try { var request = (FtpWebRequest)WebRequest.Create(requestUriString); request.Credentials = new NetworkCredential(username, password); // 替换成ListDirectory,只拿纯文件名 request.Method = WebRequestMethods.Ftp.ListDirectory; request.UsePassive = true; using (WebResponse response = (FtpWebResponse)request.GetResponse()) using (Stream responseStream = response.GetResponseStream()) using (var reader = new StreamReader(responseStream)) { string line; while ((line = reader.ReadLine()) != null) { try { lines.Add(line); } catch (Exception ex) { MessageBox.Show(ex.Message); } } } } catch (Exception ex) { throw new Exception("An error occurred connecting to the website.", ex); } return lines.ToArray(); }
方案2:解析详细列表,过滤特殊项并提取文件名(适合需要文件属性的场景)
如果你需要文件的权限、大小这些信息,那得手动解析ListDirectoryDetails的输出。注意不同FTP服务器的输出格式不一样(Unix/Linux和Windows IIS的格式差异很大),这里给你一个通用的解析思路:
- 先过滤掉
.和..这两个特殊条目 - 根据服务器的输出格式,从每行里提取出文件名
下面是针对Unix风格FTP服务器的解析示例代码:
// 解析ListDirectoryDetails返回的详细行,提取文件名 public static List<string> ParseFtpDirectoryLines(string[] directoryLines) { var validFileNames = new List<string>(); foreach (var line in directoryLines) { var trimmedLine = line.TrimEnd(); // 跳过当前目录和上级目录的条目 if (trimmedLine.EndsWith(".") || trimmedLine.EndsWith("..")) continue; // Unix格式的行:分割后,文件名从第8个元素开始(前面是权限、链接数、用户、组、大小、月、日、时间) var lineParts = line.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries); if (lineParts.Length >= 8) { // 处理带空格的文件名,把后面的部分拼接起来 string fileName = string.Join(" ", lineParts.Skip(7)); // 去掉文件名可能带的引号 fileName = fileName.Trim('"'); validFileNames.Add(fileName); } } return validFileNames; }
然后在你的原方法里,调用这个解析方法来处理结果:
// 原方法中获取lines之后 var parsedFileNames = ParseFtpDirectoryLines(lines.ToArray()); return parsedFileNames.ToArray();
小提示
调试的时候可以把lines里的每一行内容打印出来,看看你的FTP服务器返回的具体格式是什么样的——这样你就能更精准地调整解析逻辑,比如如果是Windows IIS的FTP服务器,输出格式会是类似08-10-23 12:00PM <DIR> docs这样的,解析逻辑就得对应调整啦。
内容的提问来源于stack exchange,提问作者David B
相关产品推荐
相关产品推荐

