Eine POST- oder PUT-Anforderung schlägt fehl, wenn Sie die HttpWebRequest-Klasse verwenden, um viele Daten zu senden
Dieser Artikel hilft Ihnen, ein Problem zu beheben, bei dem ein Fehler ausgelöst werden kann, wenn Sie mithilfe der HttpWebRequest Klasse viele Daten auf einem Computer senden, auf dem microsoft .NET Framework ausgeführt wird.
Ursprüngliche Produktversion: .NET Framework
Ursprüngliche KB-Nummer: 908573
Problembeschreibung
Wenn Sie die HttpWebRequest Klasse verwenden, um viele Daten mithilfe einer oder einer Anforderung zu POST PUT senden, schlägt die Anforderung möglicherweise auf einem Computer fehl, auf dem die .NET Framework ausgeführt wird. Darüber hinaus erhalten Sie möglicherweise eine Fehlermeldung zu einem nicht genügend Arbeitsspeicher oder zu einem Timeout.
Wenn Sie keine Fehlermeldung zu nicht genügend Arbeitsspeicher oder Timeout erhalten, stellen Sie möglicherweise fest, dass die Anwendung, die die Klasse verwendet, HttpWebRequest viele Fehler verwendet. Wenn Sie den Leistungsmonitor verwenden, um die Anwendung zu überwachen, die die HttpWebRequest Klasse verwendet, nimmt die Anzahl der privaten Bytes weiter zu, wenn Daten gesendet werden. Daher kann es auch zu einer langsamen Leistung auf dem Computer und in anderen Anwendungen kommen, da eine höhere Speicher- und Ressourcenauslastung auftritt.
Hinweis
Die Datenmenge, die standardmäßig hochgeladen werden kann, hängt vom Arbeitsspeicher und den ressourcen ab, die auf dem Computer verfügbar sind.
Ursache
Dieses Problem tritt auf, weil die .NET Framework die ausgehenden Daten standardmäßig puffert, wenn Sie die HttpWebRequest Klasse verwenden.
Problemumgehung
Um dieses Problem zu umgehen, legen Sie die HttpWebRequest.AllowWriteStreamBuffering Eigenschaft auf "false" fest.
Fehler, der durch die Problemumgehung verursacht wird
Möglicherweise wird eine Fehlermeldung wie im folgenden Beispiel angezeigt, wenn Sie die HttpWebRequest.AllowWriteStreamBuffering Eigenschaft auf "false" festlegen:
Diese Anforderung erfordert das Puffern von Daten, damit die Authentifizierung der Umleitung erfolgreich ist.
Um viele Daten erfolgreich mithilfe einer POST oder einer Anforderung zu PUT senden, wenn die Eigenschaft auf HttpWebRequest.AllowWriteStreamBuffering "false" festgelegt ist, verwenden Sie je nach der zu verwendenden Authentifizierungsmethode eine der folgenden Methoden.
Anonyme Authentifizierung
Wenn der Webserver für die Verwendung der anonymen Authentifizierung konfiguriert ist, legen Sie die HttpWebRequest.AllowWriteStreamBuffering Eigenschaft auf "false" fest. Es sind keine weiteren Änderungen erforderlich.
Standardauthentifizierung
Wenn der Internetinformationsdienste(IIS)-Webserver für die Verwendung der Standardauthentifizierung konfiguriert ist und Sie die HttpWebRequest.AllowWriteStreamBuffering Eigenschaft auf "false" festlegen können, müssen Sie eine HEAD Anforderung senden, um die Verbindung vorab zu authentifizieren, bevor Sie die POST PUT Oder-Anforderung senden. Sie sollten die Eigenschaft auch HttpWebRequest.PreAuthenticate auf "true" festlegen. Senden Sie dann das POST oder PUT die Anforderung, und empfangen Sie dann die Antwort. Verwenden Sie dazu Code wie im folgenden Codebeispiel.
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();
}
Hinweis
Je nachdem, wie die Anwendung entworfen wurde, müssen Sie möglicherweise nicht jede Anforderung vorab authentifizieren, indem Sie eine HEAD Anforderung senden.
Integrierte Windows-Authentifizierung
Sie können einen Computer konfigurieren, auf dem IIS installiert ist, um zu antworten, indem Sie NTLM-Windows Authentifizierung (Negotiate) oder Windows Challenge/Response (NTLM) verwenden. Wenn IIS für die Verwendung von "Aushandeln" für Windows Authentifizierung konfiguriert ist, kann der Client entweder Kerberos oder NTLM zur Authentifizierung verwenden. Wenn IIS für die Verwendung der NTLM-Authentifizierung konfiguriert ist, kann nur die NTLM-Authentifizierung verwendet werden, und die Kerberos-Authentifizierung wird nicht unterstützt.
Wenn Sie die Kerberos-Authentifizierung aushandeln, verwenden Sie die folgende Problemumgehung. Die Problemumgehung schlägt fehl, wenn NTLM verwendet wird.
Aushandeln mit Kerberos-Authentifizierung
Wenn der IIS-Webserver für die Verwendung der Aushandlungsauthentifizierung konfiguriert ist und Sie die HttpWebRequest.AllowWriteStreamBuffering Eigenschaft auf "false" festlegen müssen, müssen Sie eine HEAD-Anforderung senden, um die Verbindung vorab zu authentifizieren, bevor Sie die POST- oder PUT-Anforderung senden. Sie können die Eigenschaft auch HttpWebRequest.PreAuthenticate auf "true" festlegen. Darüber hinaus müssen Sie die Eigenschaft möglicherweise HttpWebRequest.UnsafeAuthenticatedConnectionSharing auf "true" festlegen. Senden Sie dann die POST- oder PUT-Anforderung, und empfangen Sie dann die Antwort. Dazu können Sie Code verwenden, der dem folgenden Codebeispiel ähnelt.
Hinweis
Diese Problemumgehung schlägt fehl, wenn der Client Kerberos nicht mit negotiate-Authentifizierung verwenden kann. Sie müssen außerdem sicherstellen, dass die HttpWebRequest.KeepAlive Eigenschaft auf "true" festgelegt ist. Standardmäßig ist die Einstellung für die HttpWebRequest.KeepAlive Eigenschaft "true". Die Logik für Die Kerberos- und Standardauthentifizierung ist nahezu identisch.
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();
}
Hinweis
Je nachdem, wie die Anwendung entworfen wurde, müssen Sie möglicherweise nicht jede Anforderung vorab authentifizieren, indem Sie eine HEAD-Anforderung senden.
NTLM-Authentifizierung
Wenn der IIS-Webserver auch für die Verwendung der NTLM-Authentifizierung mit Windows-Integrated Authentifizierung konfiguriert ist und Sie die HttpWebRequest.AllowWriteStreamBuffering Eigenschaft auf "false" festlegen müssen, können Sie den Authentifizierungstyp im Clientcode auf NTLM festlegen. Nachdem Sie IIS für die Verwendung der Negotiate- und NTLM-Authentifizierung konfiguriert und den Authentifizierungstyp im Clientcode auf NTLM festgelegt haben, können Sie konfigurieren, wie IIS Authentifizierungsanforderungen verarbeitet, indem Sie die AuthPersistSingleRequest Eigenschaft in der IIS-Metabasis auf "false" festlegen.
Hinweis
Weitere Informationen zum Konfigurieren von IIS zur Unterstützung der Aushandlung und der NTLM-Authentifizierung finden Sie im Abschnitt "Verweise".
Sie müssen auch eine HEAD Anforderung senden, um die Verbindung vorab zu authentifizieren, bevor Sie die POST Anforderung senden, und die Eigenschaft auf HttpWebrequest.UnsafeAuthenticatedConnectionSharing "true" festlegen. Legen Sie dann die HttpWebRequest.PreAuthenticate Eigenschaft auf "false" fest. Senden Sie schließlich die anforderung oder senden POST PUT Sie die Antwort. Verwenden Sie dazu Code, der dem folgenden Codebeispiel ähnelt.
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();
}
Hinweis
Je nachdem, wie die Anwendung entworfen wurde, müssen Sie möglicherweise nicht jede Anforderung vorab authentifizieren, indem Sie eine HEAD Anforderung senden.