【问题标题】:How to get the last-modified date of files on FTP server如何获取 FTP 服务器上文件的最后修改日期
【发布时间】:2015-02-20 16:12:25
【问题描述】:

这是我的代码

FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(FTPAddress);
ftpRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
FtpWebResponse response = (FtpWebResponse)ftpRequest.GetResponse();
StreamReader streamReader = new StreamReader(response.GetResponseStream());

List<string> directories = new List<string>();

string line = streamReader.ReadLine();
while (!string.IsNullOrEmpty(line))
{
    directories.Add(line);
    line = streamReader.ReadLine();
}

如你所见,我使用的是ListDirectoryDetails

directories 中的每一行,内容如下:

ftp://172.28.4.7//12-22-14  01:21PM                 9075 fileName.xml

我的问题是如何从那条线上获取时间?我应该解析字符串吗?我不这么认为,因为我读到有 LastModified 属性,但我不知道如何使用它。

你能帮帮我吗?

【问题讨论】:

    标签: c# .net ftp ftpwebrequest


    【解决方案1】:

    不幸的是,没有真正可靠和有效的方法来使用 .NET 框架提供的功能来检索目录中所有文件的修改时间戳,因为它不支持 FTP MLSD 命令。 MLSD 命令以标准化的机器可读格式提供远程目录列表。命令和格式由RFC 3659标准化。

    .NET 框架支持的您可以使用的替代方案:

    • ListDirectoryDetails 方法(FTP LIST 命令)检索目录中所有文件的详细信息,然后处理 FTP 服务器特定格式的详细信息

      DOS/Windows 格式:C# class to parse WebRequestMethods.Ftp.ListDirectoryDetails FTP response
      *nix 格式:Parsing FtpWebRequest ListDirectoryDetails line

    • GetDateTimestamp 方法(FTP MDTM 命令)单独检索每个文件的时间戳。一个优点是响应由RFC 3659 标准化为YYYYMMDDHHMMSS[.sss]。缺点是您必须为每个文件发送单独的请求,这可能效率很低。此方法使用您提到的LastModified property

        const string uri = "ftp://example.com/remote/path/file.txt";
        FtpWebRequest request = (FtpWebRequest)WebRequest.Create(uri);
        request.Method = WebRequestMethods.Ftp.GetDateTimestamp;
        FtpWebResponse response = (FtpWebResponse)request.GetResponse();
        Console.WriteLine("{0} {1}", uri, response.LastModified);
      

    或者,您可以使用支持现代 MLSD 命令的第 3 方 FTP 客户端实现。

    例如WinSCP .NET assembly 支持。

    // Setup session options
    SessionOptions sessionOptions = new SessionOptions
    {
        Protocol = Protocol.Ftp,
        HostName = "example.com",
        UserName = "username",
        Password = "password",
    };
    
    using (Session session = new Session())
    {
        // Connect
        session.Open(sessionOptions);
    
        // Get list of files in the directory
        string remotePath = "/remote/path/";
        RemoteDirectoryInfo directoryInfo = session.ListDirectory(remotePath);
    
        foreach (RemoteFileInfo fileInfo in directoryInfo.Files)
        {
            Console.WriteLine("{0} {1}", fileInfo.Name, fileInfo.LastWriteTime);
        }    
    }
    

    (我是 WinSCP 的作者)

    【讨论】:

      【解决方案2】:

      尝试使用 MS 文档中的代码:

        // Get the object used to communicate with the server.
        Uri serverUri = new Uri("ftp://mypath/myfile.txt");
        FtpWebRequest request = (FtpWebRequest)WebRequest.Create (serverUri);
        request.Method = WebRequestMethods.Ftp.GetDateTimestamp;
        FtpWebResponse response = (FtpWebResponse)request.GetResponse ();
        DateTime lastModifiedDate = response.LastModified;
      

      http://msdn.microsoft.com/en-us/library/system.net.ftpwebresponse.lastmodified%28v=vs.110%29.aspx

      您应该为每个文件执行此操作。 要做到这一点,也并不简单。您必须从目录列表响应中解析结果。

      看看这个人是怎么做到的:Extracting file names from WebRequestMethods.Ftp.ListDirectoryDetails 您应该能够在读取的每一行上执行一次 foreach。

      【讨论】:

        【解决方案3】:

        这已经有几年了,但我想分享我的解决方案,因为我必须这样做。

        我使用了获取 FTP 目录列表的 MSDN 示例:https://docs.microsoft.com/en-us/dotnet/framework/network-programming/how-to-list-directory-contents-with-ftp

        这个正则表达式解析结果的答案(我实际上使用了 Nyerguds 的评论):https://stackoverflow.com/a/1329074/2246411

        这是我编写的一个简单的类,用于“重新膨胀”目录列表中的对象(目前它只用于顶级文件夹,但希望我可以改进它并在此处更新它:https://gist.github.com/derekantrican/9e890c06ed17ddc561d8af02e41c34c8):

        using System;
        using System.Collections.Generic;
        using System.Globalization;
        using System.IO;
        using System.Linq;
        using System.Net;
        using System.Text.RegularExpressions;
        
        namespace FTPHelper
        {
            public class FTPItem
            {
                public char[] Permissions { get; set; }
                public int Size { get; set; }
                public DateTime LastModified { get; set; }
                public string Name { get; set; }
                public string FullPath { get; set; }
        
                public override string ToString()
                {
                    return Name;
                }
            }
        
            public class FTPDirectory : FTPItem
            {
                public FTPDirectory() { }
                public FTPDirectory(FTPItem item)
                {
                    Permissions = item.Permissions;
                    Size = item.Size;
                    LastModified = item.LastModified;
                    Name = item.Name;
                    FullPath = item.FullPath;
                }
        
                public Lazy<List<FTPItem>> SubItems { get; set; }
            }
        
            public class FTPFile : FTPItem
            {
                public FTPFile() { }
                public FTPFile(FTPItem item)
                {
                    Permissions = item.Permissions;
                    Size = item.Size;
                    LastModified = item.LastModified;
                    Name = item.Name;
                    FullPath = item.FullPath;
                }
            }
        
            public class FTPClient
            {
                private string address;
                private string username;
                private string password;
        
                public FTPClient(string address, string username, string password)
                {
                    this.address = address.StartsWith("ftp://", StringComparison.OrdinalIgnoreCase) ? address : $"ftp://{address}";
                    this.username = username;
                    this.password = password;
                }
        
                public List<FTPItem> RetrieveDirectoryListingsFromFTP(string startingPath = null)
                {
                    List<FTPItem> results = new List<FTPItem>();
                    string path = !string.IsNullOrEmpty(startingPath) ? startingPath.Replace(" ", "%20") : address;
                    path = !path.StartsWith(address) ? $"{address}/{path}" : path;
        
                    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(path);
                    request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
                    request.Credentials = new NetworkCredential(username, password);
                    request.KeepAlive = false;
                    request.UseBinary = true;
                    request.UsePassive = true;
        
                    Regex directoryListingRegex = new Regex(@"^([d-])((?:[rwxt-]{3}){3})\s+\d{1,}\s+.*?(\d{1,})\s+(\w+)\s+(\d{1,2})\s+(\d{4})?(\d{1,2}:\d{2})?\s+(.+?)\s?$",
                                            RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
        
                    using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
                    {
                        using (Stream responseStream = response.GetResponseStream())
                        {
                            using (StreamReader reader = new StreamReader(responseStream))
                            {
                                string line;
                                while ((line = reader.ReadLine()) != null)
                                {
                                    Match match = directoryListingRegex.Match(line);
        
                                    FTPItem item = new FTPItem
                                    {
                                        Permissions = match.Groups[2].Value.ToArray(),
                                        Size = int.Parse(match.Groups[3].Value),
                                        LastModified = DateTime.ParseExact($"{match.Groups[4]} {match.Groups[5]} {match.Groups[6]} {match.Groups[7]}",
                                                            $"MMM dd {(match.Groups[6].Value != "" ? "yyyy" : "")} {(match.Groups[7].Value != "" ? "HH:mm" : "")}",
                                                            CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal),
                                        Name = match.Groups[8].Value,
                                        FullPath = $"{path}/{match.Groups[8].Value.Replace(" ", "%20")}",
                                    };
        
                                    if (match.Groups[1].Value == "d")
                                    {
                                        FTPDirectory dir = new FTPDirectory(item);
                                        dir.SubItems = new Lazy<List<FTPItem>>(() => RetrieveDirectoryListingsFromFTP(dir.FullPath));
                                        results.Add(dir);
                                    }
                                    else
                                    {
                                        FTPFile file = new FTPFile(item);
                                        results.Add(file);
                                    }
                                }
                            }
                        }
                    }
        
                    return results;
                }
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2011-03-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-02-26
          相关资源
          最近更新 更多