2010-11-11 19 views
13

Estoy tratando de publicar datos en el servidor que acepta datos comprimidos. El siguiente código funciona bien, pero no está comprimido. No he trabajado con compresión o Gzip beofre, por lo que cualquier ayuda se aplica.Cómo comprimir un HttpWebRequest POST

HttpWebRequest request = WebRequest.Create(uri) as HttpWebRequest; 
    request.Timeout = 600000; 
    request.Method = verb; // POST  
    request.Accept = "text/xml"; 

    if (!string.IsNullOrEmpty(data)) 
    { 
    request.ContentType = "text/xml";   

    byte[] byteData = UTF8Encoding.UTF8.GetBytes(data); 
    request.ContentLength = byteData.Length;  

    // Here is where I need to compress the above byte array using GZipStream 

    using (Stream postStream = request.GetRequestStream()) 
    { 
     postStream.Write(byteData, 0, byteData.Length);   
    } 
    }  

    XmlDocument xmlDoc = new XmlDocument(); 
    HttpWebResponse response = null; 
    StreamReader reader = null; 
    try 
    { 
    response = request.GetResponse() as HttpWebResponse; 
    reader = new StreamReader(response.GetResponseStream()); 
    xmlDoc.LoadXml(reader.ReadToEnd()); 
    } 

¿Descomprimo toda la matriz de bytes? ¿Debo agregar otros encabezados o eliminar el que ya está allí?

Gracias!

-Scott

Respuesta

3

En caso Page_Load:

 Response.AddHeader("Content-Encoding", "gzip"); 

Y para hacer peticiones comprimidos:

HttpWebRequest and GZip Http Responses por Rick Strahl

+4

El artículo enlazado explica cómo descomprimir datos devueltos en una respuesta, pero no la forma de estructurar la solicitud usando datos comprimidos. – Scott

+0

@Scott Actualizado. –

12

Para responder a la pregunta que hizo, a POST datos comprimidos, todo lo que necesita hacer es ajustar la secuencia de solicitud con un gzip stre soy

using (Stream postStream = request.GetRequestStream()) 
{ 
    using(var zipStream = new GZipStream(postStream, CompressionMode.Compress)) 
    { 
     zipStream.Write(byteData, 0, byteData.Length);   
    } 
} 

Esto es completamente diferente a solicitar una respuesta gzip, que es una cosa mucho más común de hacer.

+3

Esto se ve bastante cerca de lo que estoy buscando. Sin embargo, recibo una excepción "no se puede cerrar exc de flujo hasta que se escriban todos los bytes". Todavía estoy investigando eso. Flush() no parece ayudar. Además, todavía necesito saber qué encabezados usar para esto. – Scott

+0

con @filipov [respuesta] (http://stackoverflow.com/a/23055905/492258) esto se convierte en respuesta completa –

0

Pruebe este método de extensión. La transmisión se dejará abierta (consulte el constructor de GZipStream). La posición de secuencia se establece en 0 después de que se realiza la compresión.

public static void GZip(this Stream stream, byte[] data) 
{ 
    using (var zipStream = new GZipStream(stream, CompressionMode.Compress, true)) 
    { 
     zipStream.Write(data, 0, data.Length); 
    } 
    stream.Position = 0; 
} 

Usted puede utilizar la siguiente prueba:

[Test] 
public void Test_gzip_data_is_restored_to_the_original_value() 
{ 
    var stream = new MemoryStream(); 
    var data = new byte[]{1,2,3,4,5,6,7,8,9,10}; 

    stream.GZip(data); 

    var decompressed = new GZipStream(stream, CompressionMode.Decompress); 

    var data2 = new byte[10]; 
    decompressed.Read(data2,0,10); 

    Assert.That(data, Is.EqualTo(data2)); 
} 

Para más información ver: http://msdn.microsoft.com/en-us/library/hh158301(v=vs.110).aspx

3

También recibió el "se puede Stream no se cerrará hasta que todos los bytes se escriben" error utilizando un código similar al tnyfst's El problema fue que tuve:

request.ContentLength = binData.Length; 

donde binData es mi información en bruto antes de la compresión. Es evidente que la longitud del contenido comprimido sería diferente, por lo que acaba de sacar esta línea y terminó con este código:

using (GZipStream zipStream = new GZipStream(request.GetRequestStream(), CompressionMode.Compress)) 
{ 
    zipStream.Write(binData, 0, binData.Length); 
} 
Cuestiones relacionadas