2010-05-29 2 views
9

Je suis mon COMPRESSION flux de sortie via un filtre d'action:asp.net mvc flux de compression et de supprimer les espaces

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

Ce qui fonctionne très bien. Maintenant, je voudrais également supprimer l'espace présent en excès. J'ai trouvé le module http de Mads Kristensen 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)); 
    } 

j'ai ajouté la classe WhitespaceFilter et a ajouté un nouveau filtre comme la compression:

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

Cela fonctionne également très bien. Cependant, je semble avoir des problèmes en combinant les deux!

J'ai essayé:

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

Cependant, cela se traduit par des problèmes majeurs. Le code HTML est complètement foiré et parfois je reçois une erreur 330.

Il semble que la méthode d'écriture du filtre Whitespace soit appelée plusieurs fois. La première fois que la chaîne html est bien, mais sur les appels suivants, ses caractères juste au hasard.

Je pensais que c'était peut-être parce que le flux avait été dégonflé, mais n'est pas le filtre d'espaces en utilisant le flux intact et en passant le flux résultant à l'appel DeflateStream?

Des idées?

+4

Pourquoi ne pas l'enlever si vous voulez simplement le comprimer? Je m'inquiéterais seulement si je livrais les résultats non compressés. Les espaces blancs se compriment vraiment bien. – tvanfosson

+2

Fiddler montre qu'avec des espaces supprimés, la taille du fichier est un peu plus petite, mais dans un projet réel, vous avez raison; la différence serait négligeable. Je suis juste intéressé de savoir pourquoi cela ne fonctionne pas quand il semble que ce devrait être le cas. –

+0

Voir les résultats de ce gars si vous compressez et supprimez les espaces: http://stackoverflow.com/questions/855526/removing-extra-whitespace-from-generated-html-in-mvc – eadam

Répondre

7

Pour ceux qui sont loin ... vous pouvez le faire ... juste échanger l'ordre du flux chaînage:

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

J'ai fait un test avec des performances. Couper les espaces blancs dans l'exécution est horrible. De 200 rps il est tombé à 20 rps. – BrunoLM

0

Je ne vois pas beaucoup de mal avec le code ci-dessus mais vous pouvez essayer cette approche:

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

utilisez-vous BTW cette approche d'attribut lors de l'application de la compression et la suppression des espaces blancs:

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

DaTribe

Questions connexes