首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >用于解析WebRequestMethods.Ftp.ListDirectoryDetails FTP响应的C#类

用于解析WebRequestMethods.Ftp.ListDirectoryDetails FTP响应的C#类
EN

Stack Overflow用户
提问于 2011-08-15 09:37:02
回答 4查看 28.4K关注 0票数 21

我正在创建一个服务来监视FTP位置是否有新的更新,并且需要能够使用WebRequestMethods.Ftp.ListDirectoryDetails方法解析从FtpWebRequest响应返回的响应。如果所有响应都遵循相同的格式,这将是相当容易的,但不同的FTP服务器软件提供不同的响应格式。

例如,可以返回:

代码语言:javascript
复制
08-10-11  12:02PM       <DIR>          Version2
06-25-09  02:41PM            144700153 image34.gif
06-25-09  02:51PM            144700153 updates.txt
11-04-10  02:45PM            144700214 digger.tif

而另一台服务器可能会返回:

代码语言:javascript
复制
d--x--x--x    2 ftp      ftp          4096 Mar 07  2002 bin
-rw-r--r--    1 ftp      ftp        659450 Jun 15 05:07 TEST.TXT
-rw-r--r--    1 ftp      ftp      101786380 Sep 08  2008 TEST03-05.TXT
drwxrwxr-x    2 ftp      ftp          4096 May 06 12:24 dropoff

而且还观察到了其他差异,所以很可能会有一些我还没有遇到的细微差异。

有没有人知道一个完全托管(不需要访问Windows外部dll )的C#类可以无缝地处理这些情况?

我只需要列出包含以下详细信息的目录内容:文件/目录名、上次更新或创建的时间戳、文件/目录名。

预先感谢你的任何建议,Gavin

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-08-15 18:40:06

我遇到的一个解决方案是EdtFTPnet

EdtFTPnet似乎是一个很有特色的解决方案,可以处理很多不同的FTP选项,所以非常理想。

这是我在http://www.ftp2rss.com上使用的免费开源解决方案(这是我自己需要的一个小工具,但我觉得可能对其他人也有用)。

票数 4
EN

Stack Overflow用户

发布于 2016-09-29 21:04:33

对于第一个(DOS/Windows)清单,此代码将执行以下操作:

代码语言:javascript
复制
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://ftp.example.com/");
request.Credentials = new NetworkCredential("user", "password");
request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream());

string pattern = @"^(\d+-\d+-\d+\s+\d+:\d+(?:AM|PM))\s+(<DIR>|\d+)\s+(.+)$";
Regex regex = new Regex(pattern);
IFormatProvider culture = CultureInfo.GetCultureInfo("en-us");
while (!reader.EndOfStream)
{
    string line = reader.ReadLine();
    Match match = regex.Match(line);
    string s = match.Groups[1].Value;
    DateTime modified =
        DateTime.ParseExact(s, "MM-dd-yy  hh:mmtt", culture, DateTimeStyles.None);
    s = match.Groups[2].Value;
    long size = (s != "<DIR>") ? long.Parse(s) : 0;
    string name = match.Groups[3].Value;

    Console.WriteLine(
        "{0,-16} size = {1,9}  modified = {2}",
        name, size, modified.ToString("yyyy-MM-dd HH:mm"));
}

您将获得:

代码语言:javascript
复制
Version2         size =         0  modified = 2011-08-10 12:02
image34.gif      size = 144700153  modified = 2009-06-25 14:41
updates.txt      size = 144700153  modified = 2009-06-25 14:51
digger.tif       size = 144700214  modified = 2010-11-04 14:45

有关其他(*nix)列表,请参见my answer to Parsing FtpWebRequest ListDirectoryDetails line

但是,实际上,尝试解析ListDirectoryDetails返回的列表并不是正确的方法。

您希望使用支持现代MLSD命令的FTP客户端,该命令以RFC 3659中指定的机器可读格式返回目录列表。在与不支持LIST命令的过时FTP服务器(如Microsoft IIS FTP服务器)交谈时,应将解析由古老的FTP命令(由FtpWebRequest内部用于其ListDirectoryDetails方法)返回的人类可读格式用作最后的手段。

例如,对于WinSCP .NET assembly,您可以使用它的Session.ListDirectorySession.EnumerateRemoteFiles方法。

它们在内部使用MLSD命令,但可以退回到LIST命令,并支持数十种不同的人类可读的列表格式。

返回的清单显示为具有以下属性的RemoteFileInfo instances集合:

  • Name
  • LastWriteTime (具有正确的timezone)
  • Length
  • FilePermissions (解析为单独的rights)
  • Group
  • Owner
  • IsDirectory
  • IsParentDirectory
  • IsThisDirectory

(我是WinSCP的作者)

大多数其他第三方库也会做同样的事情。出于此目的,使用FtpWebRequest class是不可靠的。不幸的是,在.NET框架中没有其他内置的FTP客户端。

票数 14
EN

Stack Overflow用户

发布于 2013-11-19 11:10:44

我也面临着同样的问题,并且使用正则表达式构建了一个简单的(尽管不是非常健壮的)解决方案,使用捕获组从每行中解析出相关信息:

代码语言:javascript
复制
public static Regex FtpListDirectoryDetailsRegex = new Regex(@".*(?<month>(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec))\s*(?<day>[0-9]*)\s*(?<yearTime>([0-9]|:)*)\s*(?<fileName>.*)", RegexOptions.Compiled | RegexOptions.IgnoreCase);

然后,您可以通过以下方式从捕获组中提取值:

代码语言:javascript
复制
        string ftpResponse = "-r--r--r-- 1 ftp ftp              0 Nov 19 11:08 aaa.txt";
        Match match = FtpListDirectoryDetailsRegex.Match(ftpResponse);
        string month = match.Groups["month"].Value;
        string day = match.Groups["day"].Value;
        string yearTime = match.Groups["yearTime"].Value;
        string fileName = match.Groups["fileName"].Value;

需要注意的事项有:

  • 此选项仅适用于上述ftpResponse变量中所述格式的目录响应。在我的例子中,我很幸运每次只能访问相同的FTP服务器,所以响应格式不太可能改变。
  • yearTime变量可以表示文件时间戳的年份或时间。您需要通过查找冒号:字符的实例来手动解析它,冒号:字符将指示此捕获组包含时间而不是年份
票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7060983

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档