2011-06-06 8 views
7

Obtengo una excepción de falta de memoria cuando uso Http.Put de un archivo grande. Estoy usando un modelo asíncrono como se muestra en el código. Estoy tratando de enviar bloques de datos 8K a un servidor Windows 2008 R2. La excepción se produce consistentemente cuando intento escribir un bloque de datos que supera los 536,868,864 bytes. La excepción se produce en el método requestStream.Write en el fragmento de código a continuación.Excepción de memoria insuficiente cuando se utiliza HttpWebRequest para transmitir archivos de gran tamaño

Buscando razones por qué?

Nota: Los archivos más pequeños se PONEN BIEN. La lógica también funciona si escribo en un FileStream local. Ejecutando VS 2010, .Net 4.0 en la computadora cliente Win 7 Ultimate.

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("Http://website/FileServer/filename"); 
    request.Method = WebRequestMethods.Http.Put; 
    request.SendChunked = true; 
    request.AllowWriteStreamBuffering = true; 
    ... 

    request.BeginGetRequestStream(new AsyncCallback(EndGetStreamCallback), state); 
    ... 

    int chunk = 8192; // other values give same result 
    .... 

    private static void EndGetStreamCallback(IAsyncResult ar) { 
     long limit = 0; 
     long fileLength; 
     HttpState state = (HttpState)ar.AsyncState; 

     Stream requestStream = null; 
     // End the asynchronous call to get the request stream. 

     try { 
      requestStream = state.Request.EndGetRequestStream(ar); 
      // Copy the file contents to the request stream. 

      FileStream stream = new FileStream(state.FileName, FileMode.Open, FileAccess.Read, FileShare.None, chunk, FileOptions.SequentialScan); 

      BinaryReader binReader = new BinaryReader(stream); 
      fileLength = stream.Length; 

      // Set Position to the beginning of the stream. 
      binReader.BaseStream.Position = 0; 

      byte[] fileContents = new byte[chunk]; 

      // Read File from Buffer 
      while (limit < fileLength) 
      { 
       fileContents = binReader.ReadBytes(chunk); 

       // the next 2 lines attempt to write to network and server 
       requestStream.Write(fileContents, 0, chunk); // causes Out of memory after 536,868,864 bytes 
       requestStream.Flush(); // I get same result with or without Flush 

       limit += chunk; 
      } 

      // IMPORTANT: Close the request stream before sending the request. 
      stream.Close(); 

      requestStream.Close(); 
     } 
    } 
+1

¿Ocurre lo mismo con POST? ¿Su código realmente envía datos? – svick

+0

Es posible que desee examinar el nuevo método 'CopyTo()' de .NET 4 para las transmisiones – Cameron

Respuesta

16

Aparentemente tiene this documented problem. Cuando AllowWriteStreamBuffering es true, almacena todos los datos escritos en la solicitud! Por lo tanto, la "solución" es establecer que la propiedad de false:

Para evitar este problema, establezca la propiedad HttpWebRequest.AllowWriteStreamBuffering en falso.

+1

. También se menciona en [la documentación] (http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest). .allowwritestreambuffering.aspx): "Establecer AllowWriteStreamBuffering en true puede causar problemas de rendimiento al cargar grandes conjuntos de datos porque el búfer de datos podría usar toda la memoria disponible." – svick

+0

Sí, hemos intentado esto y seguimos teniendo problemas al establecer eso en verdadero o falso. Espero que la solución real sea no usar PUT o POST para hacer actualizaciones, sino usar una tecnología de nivel más bajo como WCF o POS (Plain Ole Sockets lol). – pearcewg

+0

@pearcewg: ¡Agregue una actualización a su pregunta (o su propia respuesta!) Si encuentra una manera segura de hacerlo funcionar, también tengo curiosidad, y sería bueno tener una referencia a consulte en el futuro ;-) – Cameron

Cuestiones relacionadas