简体   繁体   English

如何获取FTP服务器上文件的最后修改日期

[英]How to get the last-modified date of files on FTP server

This is my code这是我的代码

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();
}

As you see, I am using ListDirectoryDetails .如您所见,我使用的是ListDirectoryDetails

For every line in the directories , this is the content:对于directories每一行,这是内容:

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

My question is how to get the time from that line?我的问题是如何从那条线上获得时间? Should I parse the string?我应该解析字符串吗? I don't think so because I read that there is the LastModified property, but I don't know how to use it.我不这么认为,因为我读到有LastModified属性,但我不知道如何使用它。

Could you help me please?请问你能帮帮我吗?

Unfortunately, there's no really reliable and efficient way to retrieve modification timestamp of all files in a directory using features offered by .NET framework, as it does not support the FTP MLSD command.不幸的是,没有真正可靠和有效的方法来使用 .NET 框架提供的功能检索目录中所有文件的修改时间戳,因为它不支持 FTP MLSD命令。 The MLSD command provides a listing of remote directory in a standardized machine-readable format. MLSD命令以标准化的机器可读格式提供远程目录列表。 The command and the format is standardized by RFC 3659 .命令和格式由RFC 3659标准化。

Alternatives you can use, that are supported by .NET framework:您可以使用的替代方案,它们受 .NET 框架支持:

  • ListDirectoryDetails method (the FTP LIST command) to retrieve details of all files in a directory and then you deal with FTP server specific format of the details ListDirectoryDetails方法(FTP LIST命令)检索目录中所有文件的详细信息,然后您处理 FTP 服务器特定格式的详细信息

    DOS/Windows format: C# class to parse WebRequestMethods.Ftp.ListDirectoryDetails FTP response DOS/Windows 格式: C# 类解析 WebRequestMethods.Ftp.ListDirectoryDe​​tails FTP 响应
    *nix format: Parsing FtpWebRequest ListDirectoryDetails line *nix 格式:解析 FtpWebRequest ListDirectoryDe​​tails 行

  • GetDateTimestamp method (the FTP MDTM command) to individually retrieve timestamps for each file. GetDateTimestamp方法(FTP MDTM命令)可单独检索每个文件的时间戳。 An advantage is that the response is standardized by RFC 3659 to YYYYMMDDHHMMSS[.sss] .一个优点是响应由RFC 3659标准化为YYYYMMDDHHMMSS[.sss] A disadvantage is that you have to send a separate request for each file, what can be quite inefficient.一个缺点是您必须为每个文件发送一个单独的请求,这可能非常低效。 This method uses the LastModified property that you mention:此方法使用您提到的LastModified属性

     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);

Alternatively you can use a 3rd party FTP client implementation that supports the modern MLSD command.或者,您可以使用支持现代MLSD命令的 3rd 方 FTP 客户端实现。

For example WinSCP .NET assembly supports that.例如WinSCP .NET 程序集支持这一点。

// 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);
    }    
}

(I'm the author of WinSCP) (我是 WinSCP 的作者)

Try using this code from MS documentation:尝试使用 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 http://msdn.microsoft.com/en-us/library/system.net.ftpwebresponse.lastmodified%28v=vs.110%29.aspx

You should do this for each file.您应该为每个文件执行此操作。 To do this, it is not simple either.要做到这一点,也并不简单。 You have to parse the result from your directory list response.您必须从目录列表响应中解析结果。

Check how this guy do that: Extracting file names from WebRequestMethods.Ftp.ListDirectoryDetails You should be able to do a foreach on each line read.检查这家伙是如何做到的: 从 WebRequestMethods.Ftp.ListDirectoryDe​​tails 中提取文件名您应该能够在读取的每一行上执行 foreach。

This is a few years old now, but wanted to share my solution as I just had to do this.这已经有几年了,但我想分享我的解决方案,因为我只需要这样做。

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

And this answer for a regex to parse the results (I actually used Nyerguds's comment): https://stackoverflow.com/a/1329074/2246411这个正则表达式解析结果的答案(我实际上使用了 Nyerguds 的评论): https ://stackoverflow.com/a/1329074/2246411

Here's the simple class I wrote up to "reinflate" the objects from the directory listing (currently it only does the top level folder, but hopefully I can improve it and update it here: https://gist.github.com/derekantrican/9e890c06ed17ddc561d8af02e41c34c8 ):这是我编写的简单类,用于从目录列表中“重新充气”对象(目前它只执行顶级文件夹,但希望我可以改进它并在此处更新它: 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;
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM