FTPの場所で新しい更新を監視するサービスを作成しており、WebRequestMethods.Ftp.ListDirectoryDetailsメソッドを使用してFtpWebRequest応答から返された応答を解析する機能が必要です。すべての応答が同じ形式に従っている場合はかなり簡単ですが、FTPサーバーソフトウェアが異なれば、応答形式も異なります。
たとえば、次のようになります。
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
そして、別のサーバーが戻る可能性があります。
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#クラスを知っている人はいますか?
次の詳細を含むディレクトリの内容をリストするだけで済みます:ファイル/ディレクトリ名、最終更新または作成されたタイムスタンプ、ファイル/ディレクトリ名。
提案を事前にありがとう、ギャビン
私が遭遇した1つの解決策は EdtFTPnet
EdtFTPnetは、さまざまなFTPオプションを処理する機能満載のソリューションのようであるため、理想的です。
これは私がどのように採用したかという無料のオープンソースソリューションです http://www.ftp2rss.com (私が自分で必要としていたが、他の人にも役立つかもしれないと考えた小さなツール)。
最初の(DOS/Windows)リストでは、このコードは次のことを行います。
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);
DateTime modified =
DateTime.ParseExact(
match.Groups[1].Value, "MM-dd-yy hh:mmtt", culture, DateTimeStyles.None);
long size = (match.Groups[2].Value != "<DIR>") ? long.Parse(match.Groups[2].Value) : 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"));
}
あなたが得るでしょう:
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)リストについては、 FtpWebRequest ListDirectoryDetails行の解析に対する私の回答 を参照してください。
しかし、実際にListDirectoryDetails
によって返されたリストを解析しようとすることは、正しい方法ではありません。
RFC 3659 で指定された機械可読形式でディレクトリリストを返す最新のMLSD
コマンドをサポートするFTPクライアントを使用するとします。古代のLIST
コマンド(FtpWebRequest
メソッドのListDirectoryDetails
によって内部的に使用される)によって返される人間が読める形式を解析することは、通信するときの最後の手段として使用する必要があります。 MLSD
コマンドをサポートしない廃止されたFTPサーバー(Microsoft IIS FTPサーバーなど)。
たとえば、 WinSCP .NET Assembly の場合、その Session.ListDirectory
または Session.EnumerateRemoteFiles
メソッド。
内部的にはMLSD
コマンドを使用しますが、LIST
コマンドにフォールバックして、人間が読める形式の数十の異なるリスト形式をサポートできます。
返されるリストは、次のようなプロパティを持つ RemoteFileInfo
インスタンス のコレクションとして表示されます。
Name
LastWriteTime
(正しいタイムゾーンで)Length
FilePermissions
(個人の権利に解析されます)Group
Owner
IsDirectory
IsParentDirectory
IsThisDirectory
(私はWinSCPの作者です)
他のほとんどのサードパーティライブラリも同じことをします。 FtpWebRequest
class の使用は、この目的では信頼できません。残念ながら、.NETFrameworkには他に組み込みのFTPクライアントはありません。
私はこれと同じ問題に直面しており、正規表現を使用して単純な(それほど堅牢ではありませんが)ソリューションを構築し、キャプチャグループを使用して各行から関連情報を解析しました。
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);
次に、次の方法でキャプチャグループから値を抽出できます。
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
変数は、ファイルのタイムスタンプの年または時刻のいずれかを表すことができます。このキャプチャグループに年ではなく時間が含まれていることを示すコロン:文字のインスタンスを探して、これを手動で解析する必要があります。Ftp.dll FTPクライアント を見てください。
これには、Windows、Unix、およびNetwareプラットフォーム上のほとんどのFTPサーバー用の 自動ディレクトリリストパーサー が含まれます。
これは私が開発した商用製品であることに注意してください。