代码改变世界

Minify Action Filter Attribute in ASP.NET MVC

2013-01-23 22:29  yezhi  阅读(551)  评论(0编辑  收藏  举报
[HandleError]
public class HomeController : Controller
{
    [Minify]
    public ActionResult Index()
    {
        ViewData["Message"] = "Welcome to ASP.NET MVC!";

        return View();
    }
}

public class Minify : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (response.ContentType == "text/html")

        filterContext.HttpContext.Response.Filter = new MinifyFilter(filterContext.HttpContext.Response.Filter);

        base.OnActionExecuting(filterContext);
    }
}

public class MinifyFilter : MemoryStream
{
    private StringBuilder outputString = new StringBuilder();
    private Stream outputStream = null;

    public MinifyFilter(Stream outputStream)
    {
        this.outputStream = outputStream;
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        outputString.Append(Encoding.UTF8.GetString(buffer));
    }

    public override void Close()
    {
        //Call the minifier here, your data is in outputString
        string result = outputString.ToString().Replace(Environment.NewLine, string.Empty);

        byte[] rawResult = Encoding.UTF8.GetBytes(result);
        outputStream.Write(rawResult, 0, rawResult.Length);

        base.Close();
        outputStream.Close();
    }
}
#region Dirty work
        public override void Write(byte[] buffer, int offset, int count)
        {
            HttpResponse response = HttpContext.Current.Response;
            string charset = response.Charset ?? "utf-8";
            string finalHtml = Encoding.GetEncoding(charset).GetString(buffer, offset, count);
            Regex eof = new Regex("</html>", RegexOptions.IgnoreCase);

            if (!eof.IsMatch(finalHtml))
            {
                responseHtml.Append(finalHtml);
            }
            else
            {
                responseHtml.Append(finalHtml);
                 finalHtml = responseHtml.ToString();
                //js文本
                Regex reg = new Regex("<script[^>]*>(?<content>[^<]*)</script>", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                //js引用
                Regex regSrc = new Regex("src=\"?(?<src>[^'\">]*)\"?", RegexOptions.IgnoreCase | RegexOptions.Multiline);
                StringBuilder jsContent = new StringBuilder();
                List<string> jsSrc = new List<string>();

                MatchCollection mc = reg.Matches(finalHtml);

                if (mc.Count > 0)
                {
                    #region 找出js部分

                    foreach (Match m in mc)
                    {
                        string str = m.Groups["content"].Value;
                        if (!string.IsNullOrEmpty(str))
                        {
                            jsContent.AppendLine(str);//找出js文本
                        }
                        else
                        {
                            //找出js引用
                            Match mSrc = regSrc.Match(m.Value);
                            if (mSrc != null && mSrc.Success)
                            {
                                string temp = mSrc.Groups["src"].Value;
                                if (!jsSrc.Contains(temp))
                                    jsSrc.Add(temp);
                            }
                        }
                    }
                    #endregion

                    finalHtml = reg.Replace(finalHtml, string.Empty);

                    #region 合并js文本和js引用

                    //生成新的js引用
                    string jsFileFormat = "<script type=\"text/javascript\" src=\"{0}\"></script>";
                    string jshref = string.Format(jsFileFormat, "http://localhost:58798/js.ashx?href=" + string.Join(",", jsSrc));
                    //生成新的js文本
                    string jstextFormat = "<script type=\"text/javascript\">{0}</script>";
                    //压缩js文本
                    string jsContentstr = JavaScriptCompressor.Compress(jsContent.ToString());
                    string jsText = string.Format(jstextFormat, jsContentstr);
                    //插入新生成的js
                    int bodyindex = finalHtml.ToLower().LastIndexOf("</body>");
                    finalHtml = finalHtml.Insert(bodyindex, jshref + Environment.NewLine + jsText);
                    #endregion
                }
                byte[] data = Encoding.GetEncoding(charset).GetBytes(finalHtml);
                responseStream.Write(data, 0, data.Length);
            }

        }

        #endregion

other

string str = Request.Headers.Get("Accept-Encoding");     
if (str != null)     
{     
    Stream filter = Response.Filter;     
    str = str.ToLower();     
    if (str.Contains("gzip"))     
    {     
        Response.Filter = new GZipStream(filter, CompressionMode.Compress);     
        Response.AppendHeader("Content-Encoding", "gzip");     
    }     
    else if (str.Contains("deflate"))     
    {     
        Response.Filter = new DeflateStream(filter, CompressionMode.Compress);     
        Response.AppendHeader("Content-Encoding", "deflate");     
    }     
}