次の方法で共有


System.Net.FtpWebRequest クラスは、.NET Framework 4 と .NET Framework 3.5 では動作が異なります

この記事は、Microsoft .NET Framework 4 のクラスを使用して FTP またはRETRコマンドをSystem.Net.FtpWebRequest実行するときに発生する FTP STOR エラー 5xx を修正するのに役立ちます。

元の製品バージョン: .NET Framework
元の KB 番号: 2134299

現象

.NET Framework 4 の クラスをSystem.Net.FtpWebRequest使用して FTP STOR またはRETRコマンドを実行すると、次のように FTP エラー 5xx がスローされます。

501 構文エラー - 送信者/受信者が見つかりません。

ただし、このクラスは.NET Framework 3.5 では正常に動作し、同じエラーはスローされません。

原因

この問題の原因は、.NET Framework 4 のクラスのSystem.Net.FtpWebRequest動作の変更によるものです。 プロトコル コマンドの使用をSystem.Net.FtpWebRequest効率化するために、.NET Framework 3.5 から .NET Framework 4 にクラスがCWD変更されました。 クラスの System.Net.FtpWebRequest 新しい実装では、ユーザーが要求した実際のコマンドを発行する前に追加 CWD のコマンドが送信されるのを防ぎ、代わりに要求されたコマンドを直接送信します。 完全に RFC 準拠の FTP サーバーの場合、これは問題になりませんが、完全に RFC に準拠していないサーバーの場合は、これらの種類のエラーが表示されます。

解決方法

この問題を解決するには、コマンドを強制的System.Net.FtpWebRequestに 2.0 または 3.5 で動作する以前の動作に戻し、実際のコマンドを発行する前に余分なCWDコマンドを発行.NET Framework必要があります。

クラスのインスタンスが呼び出される前に、次のコードを配置する System.Net.FtpWebRequest 必要があります。

次のコードは、アプリケーション ドメイン全体の設定を変更するため、1 回だけ呼び出す必要があります。

private static void SetMethodRequiresCWD ()
{
    Type requestType = typeof (FtpWebRequest);
    FieldInfo methodInfoField = requestType.GetField ("m_MethodInfo", BindingFlags.NonPublic | BindingFlags.Instance);
    Type methodInfoType = methodInfoField.FieldType;
    FieldInfo knownMethodsField = methodInfoType.GetField ("KnownMethodInfo", BindingFlags.Static | BindingFlags.NonPublic);
    Array knownMethodsArray = (Array) knownMethodsField.GetValue (null);
    FieldInfo flagsField = methodInfoType.GetField ("Flags", BindingFlags.NonPublic | BindingFlags.Instance);
    int MustChangeWorkingDirectoryToPath = 0x100;
    foreach (object knownMethod in knownMethodsArray)
    {
        int flags = (int) flagsField.GetValue (knownMethod);
        flags |= MustChangeWorkingDirectoryToPath;
        flagsField.SetValue (knownMethod, flags);
    }
}

FtpWebRequest の動作の変更

クラスの動作は、System.Net.FtpWebRequest.NET Framework 4 と .NET Framework 3.5 で変更されました。

.NET Framework 3.5 では、 クラスを使用してSystem.Net.FtpWebRequestサーバーにファイルをアップロードし、次の FTP コマンドの一般的な交換に従いました。

  • USE
  • PASS
  • OPTS
  • PWD
  • CWD
  • STOR

ただし、.NET Framework 4 では、一般的なファイルアップロードでは次のコマンド シーケンスが実行されます。

  • USER
  • PASS
  • OPTS
  • PWD
  • STOR

2 つの動作の違いは、3.5 バージョンでは、現在のディレクトリを目的のディレクトリに変更するコマンドを CWD 実行し、ファイル名だけを指定したコマンドを STOR 実行することでアップロードが行われる点です。

ただし、.NET Framework 4 実装では、追加の CWD コマンドの送信を禁止し、完全修飾ディレクトリ構造を使用してコマンドを宛先ディレクトリに直接送信STORします。

完全に RFC 準拠の FTP サーバーの場合は問題になりませんが、他の場合、この動作により、既存のアプリケーションが .NET Framework 4 で動作しなくなる可能性があります。

このようなサーバー通信の場合、サーバーは FTP エラー コード 5xx (501 構文エラーなど) で応答します。送信者/受信側が見つからないのに対し、.NET Framework 3.5 で使用すると、同じコードがクラスに対System.Net.FtpWebRequestして機能します。