这是我的代码
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
属性,但我不知道如何使用它。
你能帮我吗?
答案 0 :(得分:7)
不幸的是,使用.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
命令的第三方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的作者)
答案 1 :(得分:0)
尝试使用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。
答案 2 :(得分:0)
这已经有几年历史了,但是因为我必须这样做,所以想分享我的解决方案。
我使用了获得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;
}
}
}