web-dev-qa-db-ja.com

FtpWebRequestの前にFTPにファイルが存在するかどうかを確認する方法

FtpWebRequestを使用して、FTPディレクトリにファイルを配置する必要があります。アップロードする前に、まずこのファイルが存在するかどうかを知りたいです。

このファイルが存在するかどうかを確認するには、どのメソッドまたはプロパティを使用する必要がありますか?

66
var request = (FtpWebRequest)WebRequest.Create
    ("ftp://ftp.domain.com/doesntexist.txt");
request.Credentials = new NetworkCredential("user", "pass");
request.Method = WebRequestMethods.Ftp.GetFileSize;

try
{
    FtpWebResponse response = (FtpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
    FtpWebResponse response = (FtpWebResponse)ex.Response;
    if (response.StatusCode ==
        FtpStatusCode.ActionNotTakenFileUnavailable)
    {
        //Does not exist
    }
}

一般的なルールとして、このようなコードの機能に例外を使用することはお勧めできませんが、この場合、プラグマティズムの勝利だと思います。ディレクトリの呼び出しリストは、この方法で例外を使用するよりもはるかに効率が悪い可能性があります。

そうでない場合は、良い習慣ではないことに注意してください!

編集:「それは私のために働く!」

これはほとんどのftpサーバーで機能するようですが、すべてではありません。一部のサーバーでは、SIZEコマンドが機能する前に「TYPE I」を送信する必要があります。次のように問題を解決する必要があると考えられていたでしょう。

request.UseBinary = true;

残念なことに、FtpWebRequestがファイルをダウンロードまたはアップロードしない限り、 "TYPE I"を送信しないという設計上の制限(大きなバグです!)です。ディスカッションとマイクロソフトの対応をご覧ください こちら

代わりに次のWebRequestMethodを使用することをお勧めします。これは、テストしたすべてのサーバーで機能します。ファイルサイズが返されないサーバーでも同様です。

WebRequestMethods.Ftp.GetDateTimestamp
113
user42467

なぜなら

request.Method = WebRequestMethods.Ftp.GetFileSize

場合によっては失敗する可能性があります(550:SIZE = not allowed in ASCII mode))、代わりにタイムスタンプを確認するだけです。

reqFTP.Credentials = new NetworkCredential(inf.LogOn, inf.Password);
reqFTP.UseBinary = true;
reqFTP.Method = WebRequestMethods.Ftp.GetDateTimestamp;
8

FtpWebRequest(.NETの他のクラスも)には、ファイルの存在を確認する明示的なメソッドはありません。 GetFileSizeGetDateTimestampなどのリクエストを悪用する必要があります。

string url = "ftp://ftp.example.com/remote/path/file.txt";

WebRequest request = WebRequest.Create(url);
request.Credentials = new NetworkCredential("username", "password");
request.Method = WebRequestMethods.Ftp.GetFileSize;
try
{
    request.GetResponse();
    Console.WriteLine("Exists");
}
catch (WebException e)
{
    FtpWebResponse response = (FtpWebResponse)e.Response;
    if (response.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
    {
        Console.WriteLine("Does not exist");
    }
    else
    {
        Console.WriteLine("Error: " + e.Message);
    }
}

より簡単なコードが必要な場合は、サードパーティのFTPライブラリを使用してください。

たとえば、 WinSCP .NET Assembly の場合、 Session.FileExistsメソッド

SessionOptions sessionOptions = new SessionOptions {
    Protocol = Protocol.Ftp,
    HostName = "ftp.example.com",
    UserName = "username",
    Password = "password",
};

Session session = new Session();
session.Open(sessionOptions);

if (session.FileExists("/remote/path/file.txt"))
{
    Console.WriteLine("Exists");
}
else
{
    Console.WriteLine("Does not exist");
}

(私はWinSCPの著者です)

3
Martin Prikryl