2010-05-29 65 views
9

因此,我通過一個動作濾波壓縮我的輸出流:asp.net的MVC壓縮碼流,並刪除空白

var response = filterContext.HttpContext.Response; 
response.Filter = new DeflateStream(response.Filter), CompressionMode.Compress); 

偉大的工程。現在,我還想刪除存在的多餘空白。我找到了Mads Kristensen的http模塊http://madskristensen.net/post/A-whitespace-removal-HTTP-module-for-ASPNET-20.aspx

public class WhitespaceFilter : Stream { 

    // using Mads Kristensen httpModule 
    // http://madskristensen.net/post/A-whitespace-removal-HTTP-module-for-ASPNET-20.aspx 

    private Stream os; 
    private static Regex reg = new Regex(@"^\s+", RegexOptions.Multiline | RegexOptions.Compiled); 

    public WhitespaceFilter(Stream os) { 
     this.os = os; 
    } 

    //methods that need to be overridden from stream 
    public override bool CanRead { 
     get { return true; } 
    } 

    public override bool CanSeek { 
     get { return true; } 
    } 

    public override bool CanWrite { 
     get { return true; } 
    } 

    public override void Flush() { 
     os.Flush(); 
    } 

    public override long Length { 
     get { return 0; } 
    } 

    private long _position; 
    public override long Position { 
     get { return _position; } 
     set { _position = value; } 
    } 

    public override int Read(byte[] buffer, int offset, int count) { 
     return os.Read(buffer, offset, count); 
    } 

    public override long Seek(long offset, SeekOrigin origin) { 
     return os.Seek(offset, origin); 
    } 

    public override void SetLength(long value) { 
     os.SetLength(value); 
    } 

    public override void Close() { 
     os.Close(); 
    } 

    public override void Write(byte[] buffer, int offset, int count) { 
     string html = System.Text.Encoding.Default.GetString(buffer); 

     //remove whitespace 
     html = reg.Replace(html, string.Empty); 

     byte[] outdata = System.Text.Encoding.Default.GetBytes(html); 

     //write bytes to stream 
     os.Write(outdata, 0, outdata.GetLength(0)); 
    } 

我加入了WhitespaceFilter類,並添加像壓縮新的過濾器:

var response = filterContext.HttpContext.Response; 
response.Filter = new WhitepaperFilter(response.Filter); 

這也偉大工程。但是,我似乎在將這兩者結合起來時遇到了問題!

我想:

var response = filterContext.HttpContext.Response; 
response.Filter = new DeflateStream(new WhitespaceFilter(response.Filter), CompressionMode.Compress); 

然而這會導致一些重大問題。該html完全搞砸了,有時我得到一個330錯誤。

看起來Whitespace過濾器寫入方法被多次調用。 html字符串第一次沒問題,但隨後調用它的隨機字符。

我認爲這可能是因爲流已放氣,但不是使用未觸摸的流的空白過濾器,然後將結果流傳遞給DeflateStream調用?

任何想法?

+4

爲什麼打擾刪除它,如果你只是要壓縮它呢?如果我在未壓縮的情況下提供結果,我只會擔心它。空白壓縮得很好。 – tvanfosson 2010-05-29 15:50:49

+2

Fiddler確實顯示刪除空格後文件大小比較小,但是在真實世界的項目中,您是對的;差異可以忽略不計。我只是感興趣,爲什麼這不起作用,當它看起來應該。 – 2010-05-29 16:05:54

+0

看到這個人的發現,如果你壓縮並刪除空白:http://stackoverflow.com/questions/855526/removing-extra-whitespace-from-generated-html-in-mvc – eadam 2013-08-25 04:53:47

回答

7

對於那些誰走到這一步......你可以做到這一點...只是交換流的次序鏈接:

public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     var response = filterContext.HttpContext.Response; 

     // - COMPRESS 
     HttpRequestBase request = filterContext.HttpContext.Request; 
     string acceptEncoding = request.Headers["Accept-Encoding"]; 
     if (!String.IsNullOrEmpty(acceptEncoding)) 
     { 
      acceptEncoding = acceptEncoding.ToUpperInvariant(); 

      if (acceptEncoding.Contains("GZIP")) 
      { 
       response.AppendHeader("Content-encoding", "gzip"); 
       response.Filter = new GZipStream(response.Filter, CompressionMode.Compress); 
      } 
      else if (acceptEncoding.Contains("DEFLATE")) 
      { 
       response.AppendHeader("Content-encoding", "deflate"); 
       response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress); 
      } 
     } 

     // - REMOVE WHITE SPACE 
     response.Filter = new WhitespaceFilter(response.Filter); 
    } 
+5

我做了一個測試的性能。在運行時修剪空白是可怕的。從200 rps降至20 rps。 – BrunoLM 2011-01-29 18:16:46

0

我沒有看到太多的錯誤上面,但是你可能想嘗試這種方法的代碼:

:BTW正在申請壓縮和空白去除,當你使用這個屬性的方法

var response = filterContext.HttpContext.Response; 
using(var wsf = new WhitespaceFilter(response.Filter)) 
{ 
    wsf.Flush(); 
    response.Filter = new DefalteStream(wsf, CompressMode.Compress); 
} 

http://www.avantprime.com/articles/view-article/7/compress-httpresponse-for-your-controller-actions-using-attributes

DaTribe