2011-09-15 18 views
5

Uso HttpListener para mi propio servidor http (no utilizo IIS). Quiero comprimir mi OutputStream por compresión gzip:C# HttpListener Response + GZipStream

byte[] refBuffer = Encoding.UTF8.GetBytes(...some data source...); 

var varByteStream = new MemoryStream(refBuffer); 

System.IO.Compression.GZipStream refGZipStream = new GZipStream(varByteStream, CompressionMode.Compress, false); 

refGZipStream.BaseStream.CopyTo(refHttpListenerContext.Response.OutputStream); 

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

Pero yo conseguir el error en Chrome:

ERR_CONTENT_DECODING_FAILED

Si quito AddHeader, entonces funciona, pero el tamaño de la respuesta no parece estar siendo comprimida. ¿Qué estoy haciendo mal?

+0

Es imposible que algo no se comprima debido a un encabezado, dado que en realidad está escribiendo explícitamente el contenido como comprimido. ¿Estás seguro de que Chrome no te está dando el tamaño * descomprimido * del archivo? – Ryan

+0

@minitech, buenas preguntas! Estoy tratando de verificar el tamaño real del tráfico. – Edward83

Respuesta

9

El problema es que su transferencia va en la dirección incorrecta. Lo que se quiere hacer es fijar el GZipStream a la Response.OutputStream y luego llamar CopyTo en el MemoryStream, pasando el GZipStream, así:

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

byte[] refBuffer = Encoding.UTF8.GetBytes(...some data source...); 

var varByteStream = new MemoryStream(refBuffer); 

System.IO.Compression.GZipStream refGZipStream = new GZipStream(refHttpListenerContext.Response.OutputStream, CompressionMode.Compress, false); 

varByteStream.CopyTo(refGZipStream); 
refGZipStream.Flush(); 
4

El primer problema (como se menciona por Brent M MÃÃ,¡gicas) es la posición incorrecta de la cabecera. El segundo es que no usas apropiadamente el GZipStream. Esta secuencia requiere una secuencia "superior" para escribir, lo que significa una secuencia vacía (la llenas con tu memoria intermedia). Al tener una secuencia "superior" vacía, todo lo que tienes que hacer es escribir en GZipStream tu memoria intermedia. Como resultado, la secuencia de memoria se llenará con el contenido comprimido. Entonces necesita algo como:

byte[] buffer = ....; 

using (var ms = new MemoryStream()) 
{ 
    using (var zip = new GZipStream(ms, CompressionMode.Compress, true)) 
    zip.Write(buffer, 0, buffer.Length); 
    buffer = ms.ToArray(); 
} 

response.AddHeader("Content-Encoding", "gzip"); 
response.ContentLength64 = buffer.Length; 

response.OutputStream.Write(buffer, 0, buffer.Length);