HttpWebRequest クラスを使用して大量のデータを送信すると、POST または PUT 要求が失敗する

この記事では、クラスを使用して Microsoft サーバーを実行しているコンピューターに大量のデータを送信するときにエラーがスローされる可能性がある問題を解決 HttpWebRequest .NET Framework。

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

現象

クラスを使用して、要求または要求を使用して大量のデータを送信すると、要求が失敗する可能性 HttpWebRequest POST PUT .NET Framework。 さらに、メモリ切れまたは時間切れエラー メッセージが表示される場合があります。

メモリ切れまたは時間切れエラー メッセージが表示されない場合は、クラスを使用するアプリケーションが多くのメモリを使用している場合 HttpWebRequest があります。 パフォーマンス モニターを使用してクラスを使用するアプリケーションを監視すると、データの送信に合ってプライベート バイト数 HttpWebRequest が増加し続ける。 そのため、メモリとリソースの使用率が高くなるので、コンピューターや他のアプリケーションでパフォーマンスが低下することがあります。

注意

既定でアップロードできるデータの量は、コンピューターで使用できるメモリとリソースによって異なります。

原因

この問題は、クラスを使用.NET Framework送信データを既定でバッファー処理するために発生 HttpWebRequest します。

回避策

この問題を回避するには、プロパティを HttpWebRequest.AllowWriteStreamBuffering false に設定します。

回避策によって発生するエラー

プロパティを false に設定すると、次の例のような HttpWebRequest.AllowWriteStreamBuffering エラー メッセージが表示されることがあります。

この要求では、リダイレクトの認証が成功するためにデータのバッファー処理が必要です。

プロパティが false に設定されている場合に、a または要求を使用して多数のデータを正常に送信するには、使用する認証方法に応じて、次のいずれかの方法 POST PUT HttpWebRequest.AllowWriteStreamBuffering を使用します。

匿名認証

Web サーバーが匿名認証を使用するように構成されている場合は、プロパティを HttpWebRequest.AllowWriteStreamBuffering false に設定します。 その他の変更は不要です。

基本認証

インターネット インフォメーション サービス (IIS) Web サーバーが基本認証を使用するように構成され、プロパティを false に設定できる場合は、要求を送信する前に、接続を事前認証するための要求を送信する必要があります。 HttpWebRequest.AllowWriteStreamBuffering HEAD POST PUT プロパティを true に HttpWebRequest.PreAuthenticate 設定する必要があります。 次に、要求 POSTPUT 送信し、応答を受信します。 これを行うには、次のコード例のようなコードを使用します。

public void test(Uri URL)
{
    HttpWebRequest WRequest;
    HttpWebResponse WResponse;
    //preAuth the request
    // You can add logic so that you only pre-authenticate the very first request.
    // You should not have to pre-authenticate each request.
    WRequest = (HttpWebRequest)HttpWebRequest.Create(URL);
    // Set the username and the password.
    WRequest.Credentials = new NetworkCredential(user, password);
    WRequest.PreAuthenticate = true;
    WRequest.UserAgent = "Upload Test";
    WRequest.Method = "HEAD";
    WRequest.Timeout = 10000;
    WResponse = (HttpWebResponse)WRequest.GetResponse();
    WResponse.Close();
    // Make the real request.
    WRequest = (HttpWebRequest)HttpWebRequest.Create(URL);
    // Set the username and the password.
    WRequest.Credentials = new NetworkCredential(user, password);
    WRequest.PreAuthenticate = true;
    WRequest.UserAgent = "Upload Test";
    WRequest.Method = "POST";
    WRequest.AllowWriteStreamBuffering = false;
    WRequest.Timeout = 10000;
    FileStream ReadIn = new FileStream("c:\\testuploadfile.txt", FileMode.Open, FileAccess.Read);
    ReadIn.Seek(0, SeekOrigin.Begin); // Move to the start of the file.
    WRequest.ContentLength = ReadIn.Length; // Set the content length header to the size of the file.
    Byte[] FileData = new Byte[ReadIn.Length]; // Read the file in 2 KB segments.
    int DataRead = 0;
    Stream tempStream = WRequest.GetRequestStream();
    do
    {
        DataRead = ReadIn.Read(FileData,0,2048);
        if (DataRead > 0) //we have data
        {
            tempStream.Write(FileData,0,DataRead);
            Array.Clear(FileData,0, 2048); // Clear the array.
        }
    } while (DataRead > 0);

    WResponse = (HttpWebResponse)WRequest.GetResponse();
    // Read your response data here.
    // Close all streams.
    ReadIn.Close();
    tempStream.Close();
    WResponse.Close();
}

注意

アプリケーションの設計方法によっては、要求を送信して各要求を事前認証する必要が生じない場合 HEAD があります。

統合 Windows 認証

IIS がインストールされているコンピューターを構成するには、Negotiate または Windows チャレンジ/応答 (NTLM) 認証をWindowsします。 IIS がネゴシエートを使用して認証Windows場合、クライアントは Kerberos または NTLM を使用して認証できます。 IIS が NTLM 認証を使用するように構成されている場合は、NTLM 認証のみを使用できます。Kerberos 認証はサポートされていません。

Kerberos 認証でネゴシエートを使用する場合は、次の回避策を使用します。 NTLM を使用すると、回避策は失敗します。

Kerberos 認証とのネゴシエート

IIS Web サーバーがネゴシエート認証を使用するように構成されている場合、プロパティを false に設定する必要がある場合は、POST または PUT 要求を送信する前に、接続を事前認証するための HEAD 要求を送信する必要があります。 HttpWebRequest.AllowWriteStreamBuffering プロパティを true HttpWebRequest.PreAuthenticate に設定できます。 さらに、プロパティを true に設定 HttpWebRequest.UnsafeAuthenticatedConnectionSharing する必要があります。 次に、POST または PUT 要求を送信し、応答を受信します。 これを行うには、次のコード例に似たコードを使用できます。

注意

クライアントがネゴシエート認証で Kerberos を使用できない場合、この回避策は失敗します。 また、プロパティが true に HttpWebRequest.KeepAlive 設定されている必要があります。 既定では、プロパティの設定 HttpWebRequest.KeepAlive は true です。 Kerberos 認証と基本認証のロジックはほぼ同じです。

public void test(Uri URL)
{
    HttpWebRequest WRequest;
    HttpWebResponse WResponse;
    CredentialCache myCredCache = new CredentialCache();
    myCredCache.Add(URL,"Negotiate",(NetworkCredential) CredentialCache.DefaultCredentials);
    // Pre-authenticate the request.
    WRequest = (HttpWebRequest)HttpWebRequest.Create(URL);
    // Set the username and the password.
    WRequest.Credentials = myCredCache;
    // This property must be set to true for Kerberos authentication.
    WRequest.PreAuthenticate = true;
    // Keep the connection alive.
    WRequest.UnsafeAuthenticatedConnectionSharing = true;
    WRequest.UserAgent = "Upload Test";
    WRequest.Method = "HEAD";
    WRequest.Timeout = 10000;
    WResponse = (HttpWebResponse)WRequest.GetResponse(); 
    WResponse.Close();
    // Make the real request.
    WRequest = (HttpWebRequest)HttpWebRequest.Create(URL);
    // Set the username and the password.
    WRequest.Credentials = myCredCache;
    // This property must be set to true for Kerberos authentication.
    WRequest.PreAuthenticate = true;
    // Keep the connection alive.
    WRequest.UnsafeAuthenticatedConnectionSharing = true;
    WRequest.UserAgent = "Upload Test";
    WRequest.Method = "POST";
    WRequest.AllowWriteStreamBuffering = false;
    WRequest.Timeout = 10000;
    FileStream ReadIn = new FileStream("c:\\testuploadfile.txt ", FileMode.Open, FileAccess.Read);
    ReadIn.Seek(0, SeekOrigin.Begin); // Move to the start of the file.
    WRequest.ContentLength = ReadIn.Length; // Set the content length header to the size of the file.
    Byte[] FileData = new Byte[ReadIn.Length]; // Read the file in 2 KB segments.
    int DataRead = 0;
    Stream tempStream = WRequest.GetRequestStream();
    do
    {
        DataRead = ReadIn.Read(FileData,0,2048);
        if (DataRead > 0) // We have data.
        {
            tempStream.Write(FileData,0,DataRead);
            Array.Clear(FileData,0, 2048); // Clear the array.
        }
    }while(DataRead > 0);

    WResponse = (HttpWebResponse)WRequest.GetResponse(); 
    // Read your response data here.
    // Close all streams
    ReadIn.Close();
    tempStream.Close();
    WResponse.Close();
}

注意

アプリケーションの設計方法によっては、HEAD 要求を送信して各要求を事前認証する必要が生じない場合があります。

NTLM 認証

IIS Web サーバーが Windows-Integrated 認証で NTLM 認証を使用するように構成され、プロパティを false に設定する必要がある場合は、クライアント コードで認証の種類を NTLM に設定 HttpWebRequest.AllowWriteStreamBuffering できます。 ネゴシエート認証と NTLM 認証の両方を使用する IIS を構成し、クライアント コードで認証の種類を NTLM に設定した後、IIS メタベースのプロパティを false に設定して、IIS が認証要求を処理する方法を構成できます。 AuthPersistSingleRequest

注意

ネゴシエート認証と NTLM 認証の両方をサポートするために IIS を構成する方法の詳細については、「リファレンス」 セクションを参照 してください。

また、要求を送信し、プロパティを true に設定する前に、接続を事前認証するための要求 HEAD POST HttpWebrequest.UnsafeAuthenticatedConnectionSharing を送信する必要があります。 次に、プロパティを HttpWebRequest.PreAuthenticate false に設定します。 最後に、要求を POST 送信 PUT し、応答を受信します。 これを行うには、次のコード例に似たコードを使用します。

public void test(Uri URL)
{
    HttpWebRequest WRequest;
    HttpWebResponse WResponse;
    CredentialCache myCredCache = new CredentialCache();
    myCredCache.Add(URL,"NTLM",(NetworkCredential) CredentialCache.DefaultCredentials);
    // Pre-authenticate the request.
    WRequest = (HttpWebRequest)HttpWebRequest.Create(URL);
    // Set the username and the password.
    WRequest.Credentials = myCredCache;
    // For NTLM authentication, you must set the following property to true
    // so the connection does not close.
    WRequest.UnsafeAuthenticatedConnectionSharing = true;
    WRequest.UserAgent = "Upload Test";
    WRequest.Method = "HEAD";
    WRequest.Timeout = 10000;
    WResponse = (HttpWebResponse)WRequest.GetResponse(); 
    WResponse.Close();
    // Make the real request.
    WRequest = (HttpWebRequest)HttpWebRequest.Create(URL);
    // Set the username and the password.
    WRequest.Credentials = myCredCache;
    // For NTLM authentication, you must set the following property to true
    // so the connection does not close.
    WRequest.UnsafeAuthenticatedConnectionSharing = true;
    WRequest.UserAgent = "Upload Test";
    WRequest.Method = "POST";
    WRequest.AllowWriteStreamBuffering = false;
    WRequest.Timeout = 10000;
    FileStream ReadIn = new FileStream("c:\\ testuploadfile.txt", FileMode.Open, FileAccess.Read);
    ReadIn.Seek(0, SeekOrigin.Begin); // Move to the start of the file.
    WRequest.ContentLength = ReadIn.Length; // Set the content length header to the size of the file.
    Byte[] FileData = new Byte[ReadIn.Length]; // Read the file in 2 KB segments.
    int DataRead = 0;
    Stream tempStream = WRequest.GetRequestStream();
    do
    {
        DataRead = ReadIn.Read(FileData,0,2048);
        if (DataRead > 0) // We have data.
        {
            tempStream.Write(FileData,0,DataRead);
            Array.Clear(FileData,0, 2048); // Clear the array.
        }
    }while(DataRead > 0);

    WResponse = (HttpWebResponse)WRequest.GetResponse();
    // Read your response data here.
    // Close all streams.
    ReadIn.Close();
    tempStream.Close();
    WResponse.Close();
}

注意

アプリケーションの設計方法によっては、要求を送信して各要求を事前認証する必要が生じない場合 HEAD があります。

関連情報