我正在尝试获取FTP服务器上的文件列表,然后逐个检查本地系统上是否存在该文件,是否确实比较了修改日期以及ftp文件是否更新下载。
private void btnGo_Click(object sender, EventArgs e)
{
string[] files = GetFileList();
foreach (string file in files)
{
if (file.Length >= 5)
{
string uri = "ftp://" + ftpServerIP + "/" + remoteDirectory + "/" + file;
Uri serverUri = new Uri(uri);
CheckFile(file);
}
}
this.Close();
}
public string[] GetFileList()
{
string[] downloadFiles;
StringBuilder result = new StringBuilder();
WebResponse response = null;
StreamReader reader = null;
try
{
FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "/" + remoteDirectory));
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
reqFTP.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
reqFTP.Proxy = null;
reqFTP.KeepAlive = false;
reqFTP.UsePassive = false;
response = reqFTP.GetResponse();
reader = new StreamReader(response.GetResponseStream());
string line = reader.ReadLine();
while (line != null)
{
result.Append(line);
result.Append("\n");
line = reader.ReadLine();
}
result.Remove(result.ToString().LastIndexOf('\n'), 1);
return result.ToString().Split('\n');
}
catch
{
if (reader != null)
{
reader.Close();
}
if (response != null)
{
response.Close();
}
downloadFiles = null;
return downloadFiles;
}
}
private void CheckFile(string file)
{
string dFile = file;
string[] splitDownloadFile = Regex.Split(dFile, " ");
string fSize = splitDownloadFile[13];
string fMonth = splitDownloadFile[14];
string fDate = splitDownloadFile[15];
string fTime = splitDownloadFile[16];
string fName = splitDownloadFile[17];
string dateModified = fDate + "/" + fMonth+ "/" + fYear;
DateTime lastModifiedDF = Convert.ToDateTime(dateModified);
string[] filePaths = Directory.GetFiles(localDirectory);
// if there is a file in filePaths that is the same as on the server compare them and then download if file on server is newer
foreach (string ff in filePaths)
{
string[] splitFile = Regex.Split(ff, @"\\");
string fileName = splitFile[2];
FileInfo fouFile = new FileInfo(ff);
DateTime lastChangedFF = fouFile.LastAccessTime;
if (lastModifiedDF > lastChangedFF) Download(fileName);
}
}
在检查文件方法中,对于每个文件(它们是.exe文件),当我分割字符串时,我不断得到不同的结果,即对于一个文件,文件名在第18列,另一个是在16等。我也可以总是得到文件的年份部分。
答案 0 :(得分:2)
首先,您可以在此处找到一些可以从ftp获取信息和下载数据的组件:http://www.limilabs.com/ftp
我为ftp。
编写了一些获取文件名和最后修改日期的方法这是我从行获取文件名的方式:
private string GetFtpName(string line)
{
for (int i = 0; i < 8; i++)
line = line.Substring(line.IndexOf(" ")).Trim();
return line;
}
这就是我从ftp获取最后修改日期的方式:
private DateTime GetFtpFileDate(string url, ICredentials credential)
{
FtpWebRequest rd = (FtpWebRequest)WebRequest.Create(url);
rd.Method = WebRequestMethods.Ftp.GetDateTimestamp;
rd.Credentials = credential;
FtpWebResponse response = (FtpWebResponse)rd.GetResponse();
DateTime lmd = response.LastModified;
response.Close();
return lmd;
}
答案 1 :(得分:1)
尝试
ListDirectory + GetDateTimestamp
而不是
ListDirectoryDetails
答案 2 :(得分:1)
为此,您需要检索远程目录列表,包括时间戳。
不幸的是,由于它不支持FTP MLSD
命令,因此没有真正可靠有效的方法来使用.NET框架提供的功能检索时间戳。 MLSD
命令以标准化的机器可读格式提供远程目录的列表。命令和格式由RFC 3659标准化。
.NET框架支持的替代方案(正如其他答案所示):
ListDirectoryDetails
method(FTP LIST
命令)检索目录中所有文件的详细信息,然后处理FTP服务器特定格式的详细信息(* nix格式类似于{ {1}} * nix命令是最常见的,缺点是格式可能会随着时间而改变,对于较新的文件&#34; 5月8日17:48&#34;格式用于旧文件&#34; 10月使用18 2009&#34;格式
DOS / Windows格式:C# class to parse WebRequestMethods.Ftp.ListDirectoryDetails FTP response
* nix格式:Parsing FtpWebRequest ListDirectoryDetails line
GetDateTimestamp
method(FTP ls
命令)单独检索每个文件的时间戳。一个优点是响应由RFC 3659到MDTM
标准化。缺点是你必须为每个文件发送一个单独的请求,这可能是非常低效的。
YYYYMMDDHHMMSS[.sss]
或者,您可以使用支持现代const string uri = "ftp://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);
命令的第三方FTP客户端实现。
例如WinSCP .NET assembly支持。
您可以使用Session.ListDirectory
或Session.EnumerateRemoteFiles
方法阅读返回集合中的RemoteFileInfo.LastWriteTime
文件。
或者更简单,您可以使用Session.SynchronizeDirectories
让库自动下载(同步)修改后的文件:
MLSD
(我是WinSCP的作者)
答案 3 :(得分:0)
以下是来自FTPclient来源的摘录,其中显示了他们如何构建他们的内容。 FtpFileInfo对象。我无法对此进行测试,以确保此刻可以在所有情况下使用,但也许它会给你一些想法。
/// <summary>
/// Return a detailed directory listing, and also download datetime stamps if specified
/// </summary>
/// <param name="directory">Directory to list, e.g. /pub/etc</param>
/// <param name="doDateTimeStamp">Boolean: set to True to download the datetime stamp for files</param>
/// <returns>An FTPDirectory object</returns>
public FTPdirectory ListDirectoryDetail(string directory, bool doDateTimeStamp)
{
System.Net.FtpWebRequest ftp = GetRequest(GetDirectory(directory));
// Set request to do simple list
ftp.Method = System.Net.WebRequestMethods.Ftp.ListDirectoryDetails;
string str = GetStringResponse(ftp);
// replace CRLF to CR, remove last instance
str = str.Replace("\r\n", "\r").TrimEnd('\r');
// split the string into a list
FTPdirectory dir = new FTPdirectory(str, _lastDirectory);
// download timestamps if requested
if (doDateTimeStamp)
{
foreach (FTPfileInfo fi in dir)
{
fi.FileDateTime = this.GetDateTimestamp(fi);
}
}
return dir;
}
/// <summary>
/// Obtain datetimestamp for remote file
/// </summary>
/// <param name="filename"></param>
/// <returns></returns>
public DateTime GetDateTimestamp(string filename)
{
string path;
if (filename.Contains("/"))
{
path = AdjustDir(filename);
}
else
{
path = this.CurrentDirectory + filename;
}
string URI = this.Hostname + path;
FtpWebRequest ftp = GetRequest(URI);
ftp.Method = WebRequestMethods.Ftp.GetDateTimestamp;
return this.GetLastModified(ftp);
}
答案 4 :(得分:0)
选项A:我建议你使用更高级别的FTP客户端库来处理这些细节,有几种可能的选择:
选项B:为了更直接地回答您的问题,我认为问题在于这一行:
string[] splitDownloadFile = Regex.Split(dFile, " ");
似乎FTP服务器正在使用空格来右对齐文件名。为了解决这个问题,我们希望调整正则表达式以消耗字段之间的所有空格:
string[] splitDownloadFile = Regex.Split(dFile, "\s+");
...其中\ s代表任何空格字符(通常是制表符或空格),+表示左侧的一个或多个字符。这不会处理边缘情况,例如包含空格的文件名。