2010-11-11 14 views
13

Sto tentando di inviare dati al server che accetta dati compressi. Il codice qui sotto funziona bene, ma non è compresso. Non ho lavorato con la compressione o con Gzip, quindi qualsiasi aiuto è utile.Come comprimere un POST HttpWebRequest

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()); 
    } 

Do gzip l'intero array di byte? Devo aggiungere altre intestazioni o rimuovere quello che è già lì?

Grazie!

-Scott

risposta

3

In Page_Load evento:

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

E per fare richieste compressi:

HttpWebRequest and GZip Http Responses da Rick Strahl

+4

L'articolo collegato spiega come decomprimere dati restituiti in una risposta, ma non come strutturare la richiesta utilizzando dati compressi. – Scott

+0

@Scott aggiornato. –

12

Per rispondere alla domanda che hai posto, a POST dati compressi, tutto ciò che devi fare è racchiudere il flusso della richiesta con un gzip stre am

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

Questo è completamente diverso da richiedere una risposta gzip, che è una cosa molto più comune da fare.

+3

Questo sembra abbastanza vicino a quello che sto cercando. Tuttavia, sto ricevendo un'eccezione "non posso chiudere il flusso exc fino a quando tutti i byte sono scritti". Ancora indagando su questo. Flush() non sembra aiutare. Inoltre, ho bisogno di sapere quali intestazioni usare per questo. – Scott

+0

con @filipov [risposta] (http://stackoverflow.com/a/23055905/492258) diventa una risposta completa –

0

Prova questo metodo di estensione. Lo stream verrà lasciato aperto (consultare il costruttore GZipStream). La posizione del flusso è impostata su 0 al termine della compressione.

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; 
} 

È possibile utilizzare il seguente test:

[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)); 
} 

Per ulteriori informazioni si veda: http://msdn.microsoft.com/en-us/library/hh158301(v=vs.110).aspx

3

ho anche ricevuto il "Impossibile chiudere flusso fino a quando tutti i byte sono scritti" errore utilizzando codice simile a tnyfst di. Il problema era che avevo:

request.ContentLength = binData.Length; 

dove binData è i miei dati grezzi prima della compressione. Ovviamente la lunghezza del contenuto compresso sarebbe stato diverso, così ho rimosso questa linea e si è conclusa con questo codice:

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