2011-09-15 60 views
5

我使用HttpListener爲我自己的http服務器(我不使用IIS)。我想壓縮由gzip壓縮我的OutputStream:C#HttpListener響應+ 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"); 

但我在Chrome中得到錯誤:

ERR_CONTENT_DECODING_FAILED

如果我刪除AddHeader的,那麼它的工作原理,但大小回應似乎沒有被壓縮。我究竟做錯了什麼?

+0

由於你實際上明確地寫內容爲壓縮的,所以不可能因某個頭文件而被壓縮。你確定Chrome不僅僅給你文件的解壓縮大小嗎? – Ryan

+0

@minitech,很好的問題!我試圖檢查流量的實際大小。 – Edward83

回答

9

問題是您的傳輸方向錯誤。你想要做什麼是GZipStream連接到Response.OutputStream,然後調用CopyTo從上MemoryStream的,傳入GZipStream,像這樣:

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

(如由布倫特中號拼寫提及)第一個問題是報頭的錯誤的位置。第二個是你沒有正確使用GZipStream。這個流需要一個「頂部」流寫入,意味着一個空的流(用緩衝區填充它)。有一個空的「頂級」流,那麼你所要做的就是在GZipStream上寫你的緩衝區。結果,內存流將被壓縮內容填充。所以你需要這樣的東西:

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