【问题标题】:asp.net mvc compress stream and remove whitespaceasp.net mvc 压缩流并删除空格
【发布时间】:2010-05-29 15:41:19
【问题描述】:

所以我正在通过动作过滤器压缩我的输出流:

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 调用吗?

有什么想法吗?

【问题讨论】:

  • 如果你只是想压缩它,为什么还要移除它呢?如果我提供未压缩的结果,我只会担心它。空白压缩得非常好。
  • Fiddler 确实表明,删除空格后文件大小要小得多,但是在现实世界的项目中,你是对的;差异可以忽略不计。我只是对为什么这似乎应该不起作用的原因感兴趣。
  • 如果您压缩并删除空格,请查看此人的发现:stackoverflow.com/questions/855526/…

标签: asp.net-mvc compression httpcontext


【解决方案1】:

对于那些已经走到这一步的人......你可以做到......只需交换流链接的顺序:

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

【讨论】:

  • 我做了一个性能测试。在运行时修剪空格是可怕的。从 200 rps 下降到 20 rps。
【解决方案2】:

我没有看到上面的代码有什么问题,但是您可能想尝试这种方法:

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

大部落

【讨论】:

    猜你喜欢
    • 2023-03-14
    • 2021-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-27
    • 1970-01-01
    相关资源
    最近更新 更多