Se produce un error en una solicitud POST o PUT cuando se usa la clase HttpWebRequest para enviar una gran cantidad de datos
Este artículo le ayuda a resolver un problema en el que se puede producir un error al usar la HttpWebRequest
clase para enviar una gran cantidad de datos en un equipo que ejecuta Microsoft .NET Framework.
Versión original del producto: .NET Framework
Número de KB original: 908573
Síntomas
Cuando se usa la HttpWebRequest
clase para enviar una gran cantidad de datos mediante una POST
solicitud o PUT
, la solicitud podría producir un error en un equipo que ejecuta .NET Framework. Además, puede recibir un mensaje de error de memoria insuficiente o tiempo de espera agotado.
Si no recibe un mensaje de error de memoria insuficiente o de tiempo de espera, es posible que observe que la aplicación que usa la HttpWebRequest
clase usa una gran cantidad de recuerdos. Cuando se usa Monitor de rendimiento para supervisar la aplicación que usa la HttpWebRequest
clase , el recuento de bytes privados seguirá aumentando a medida que se envíen los datos. Por lo tanto, también puede experimentar un rendimiento lento en el equipo y en otras aplicaciones porque se produce un aumento de la memoria y el uso de recursos.
Nota:
La cantidad de datos que se pueden cargar de forma predeterminada variará según la memoria y los recursos disponibles en el equipo.
Causa
Este problema se produce porque .NET Framework almacena en búfer los datos salientes de forma predeterminada cuando se usa la HttpWebRequest
clase .
Solución alternativa
Para solucionar este problema, establezca la propiedad en HttpWebRequest.AllowWriteStreamBuffering
false.
Error causado por la solución alternativa
Puede recibir un mensaje de error como el siguiente ejemplo cuando establece la propiedad en HttpWebRequest.AllowWriteStreamBuffering
false:
Esta solicitud requiere almacenar en búfer los datos para que la autenticación del redireccionamiento se realice correctamente.
Para enviar correctamente una gran cantidad de datos mediante una POST
solicitud o PUT
cuando la HttpWebRequest.AllowWriteStreamBuffering
propiedad se establece en false, use uno de los métodos siguientes, en función del método de autenticación que quiera usar.
Autenticación anónima
Si el servidor web está configurado para usar la autenticación anónima, establezca la HttpWebRequest.AllowWriteStreamBuffering
propiedad en false. No se necesitan otros cambios.
Autenticación básica
Si el servidor web de Internet Information Services (IIS) está configurado para usar la autenticación básica y puede establecer la HttpWebRequest.AllowWriteStreamBuffering
propiedad en false, debe enviar una HEAD
solicitud para autenticar previamente la conexión antes de enviar la POST
solicitud o PUT
. También debe establecer la propiedad en HttpWebRequest.PreAuthenticate
true. A continuación, envíe la POST
solicitud o PUT
y, a continuación, reciba la respuesta. Para ello, use código como el siguiente ejemplo de código.
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();
}
Nota:
En función de cómo se diseñe la aplicación, es posible que no tenga que autenticar previamente cada solicitud mediante el envío de una HEAD
solicitud.
Autenticación integrada de Windows
Puede configurar un equipo en el que IIS esté instalado para responder mediante Negotiate o Windows Challenge/Response (NTLM) autenticación de Windows. Si IIS está configurado para usar Negotiate para autenticación de Windows, el cliente puede usar Kerberos o NTLM para autenticarse. Si IIS está configurado para usar la autenticación NTLM, solo se puede usar la autenticación NTLM y no se admite la autenticación Kerberos.
Si se usa Negotiate with Kerberos authentication (Negociar con autenticación Kerberos), use la siguiente solución alternativa. La solución alternativa producirá un error si se usa NTLM.
Negociación con la autenticación Kerberos
Si el servidor web IIS está configurado para usar la autenticación Negotiate y debe establecer la HttpWebRequest.AllowWriteStreamBuffering
propiedad en false, debe enviar una solicitud HEAD para autenticar previamente la conexión antes de enviar la solicitud POST o PUT. También puede establecer la propiedad en HttpWebRequest.PreAuthenticate
true. Además, es posible que tenga que establecer la HttpWebRequest.UnsafeAuthenticatedConnectionSharing
propiedad en true. A continuación, envíe la solicitud POST o PUT y, a continuación, reciba la respuesta. Para ello, puede usar código similar al ejemplo de código siguiente.
Nota:
Esta solución alternativa producirá un error si el cliente no puede usar Kerberos con la autenticación Negotiate. También debe asegurarse de que la HttpWebRequest.KeepAlive
propiedad está establecida en true. De forma predeterminada, la configuración de la HttpWebRequest.KeepAlive
propiedad es true. La lógica para la autenticación Kerberos y básica es casi la misma.
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();
}
Nota:
En función de cómo se diseñe la aplicación, es posible que no tenga que autenticar previamente cada solicitud mediante el envío de una solicitud HEAD.
Autenticación NTLM
Si el servidor web IIS también está configurado para usar la autenticación NTLM con autenticación Windows-Integrated y debe establecer la HttpWebRequest.AllowWriteStreamBuffering
propiedad en false, puede establecer el tipo de autenticación en NTLM en el código de cliente. Después de configurar IIS para usar la autenticación Negotiate y NTLM y establecer el tipo de autenticación en NTLM en el código de cliente, puede configurar cómo IIS controla las solicitudes de autenticación estableciendo la AuthPersistSingleRequest
propiedad en la metabase de IIS en false.
Nota:
Para obtener más información sobre cómo configurar IIS para admitir la autenticación Negotiate y NTLM, consulte la sección Referencias .
También debe enviar una HEAD
solicitud para autenticar previamente la conexión antes de enviar la POST
solicitud y establecer la HttpWebrequest.UnsafeAuthenticatedConnectionSharing
propiedad en true. A continuación, establezca la HttpWebRequest.PreAuthenticate
propiedad en false. Por último, envíe la POST
solicitud o PUT
y, a continuación, reciba la respuesta. Para ello, use código similar al ejemplo de código siguiente.
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();
}
Nota:
En función de cómo se diseñe la aplicación, es posible que no tenga que autenticar previamente cada solicitud mediante el envío de una HEAD
solicitud.
Referencias
Comentarios
https://aka.ms/ContentUserFeedback.
Próximamente: A lo largo de 2024 iremos eliminando gradualmente GitHub Issues como mecanismo de comentarios sobre el contenido y lo sustituiremos por un nuevo sistema de comentarios. Para más información, vea:Enviar y ver comentarios de