用HttpCombiner来减少js和css的请问次数

HttpCombiner也不记得是谁写的了,功能是把多个js文件或css文件合并到一块,压缩一下一起发给客户端来优化网站。

用法是这样的:

 

< script  type ="text/javascript"  src ="/Part/Handle/HttpCombiner.ashx?t=js&s=a.js,b.js,dialog/c.js,dialog/d.js" ></ script > 

 

  但这样又不利于找错,所以在中间又加了一个方法,可随时控制是如上引用还是,如下一般引用:

< script  type ="text/javascript"  src ="/RES/JS/a.js" ></ script >
< script  type ="text/javascript"  src ="/RES/JS/b.js" ></ script >
< script  type ="text/javascript"  src ="/RES/JS/ dialog /c.js " ></ script >
< script  type ="text/javascript"  src ="/RES/JS/dialog/d.js" ></ script >

 

 修改后引用文件时:

<%= HttpCombiner.Requires(true,"js","a.js""b.js""dialog/c.js""dialog/d.js")%> 

第一个参数来控制合并 。

 

 一般处理程序cs源码:

using System;
using System.Web;
using System.Net;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Web.Caching;

public  class HttpCombiner : IHttpHandler
{
     #region Config
     private  const  bool DO_GZIP =  true;
     private  readonly  static TimeSpan CACHE_DURATION = TimeSpan.FromDays( 30);
     private  const  string JSPathPre =  " ~/RES/JS/ ";
     private  const  string CSSPathPre =  " ~/RES/CSS/ ";
     private  const  string CombinerUrl =  " /Part/Handle/HttpCombiner.ashx "; // 些handler路径

     private  const  string JSAbsPathPre =  " /RES/JS/ ";
     private  const  string CSSAbsPathPre =  " /RES/CSS/ ";
     #endregion


     #region Requires 默认combin
     public  static  string Requires( bool combin,  string type,  params  string[] files)
    {
         if (combin)
        {
             if (type ==  " js ")
            {
                 return  string.Format( " <script type=\"text/javascript\" src=\"{0}?t=js&s={1}\"></script> ", CombinerUrl,  string.Join( " , ", files));
            }
             else  if (type ==  " css ")
            {
                 return  string.Format( " <link rel=\"stylesheet\" type=\"text/css\" href=\"{0}?t=css&s={1}\"  /> ", CombinerUrl,  string.Join( " , ", files));
            }
             else
            {
                 return  string.Empty;
            }
        }
         else
        {
             if (type ==  " js ")
            {
                StringBuilder sb =  new StringBuilder();
                 foreach ( var file  in files)
                {
                    sb.AppendFormat( " <script type=\"text/javascript\" src=\"{0}{1}\"></script> ", JSAbsPathPre, file);
                    sb.AppendLine();
                }
                 return sb.ToString();
            }
             else  if (type ==  " css ")
            {
                StringBuilder sb =  new StringBuilder();
                 foreach ( var file  in files)
                {
                    sb.AppendFormat( " <link rel=\"stylesheet\" type=\"text/css\" href=\"{0}{1}\" /> ", CSSAbsPathPre, file);
                    sb.AppendLine();
                }
                 return sb.ToString();
            }
             else
            {
                 return  string.Empty;
            }
        }
    }
     public  static  string Requires( string type,  params  string[] files)
    {
         return Requires( true, type, files);
    }
     #endregion


     #region Process
     public  void ProcessRequest(HttpContext context)
    {

        HttpRequest request = context.Request;

         string setName = request[ " s "] ??  string.Empty;
         string contentType = request[ " t "] ??  string.Empty;
         if ( string.IsNullOrEmpty(contentType))
        {
            contentType =  " type/javascript ";
        }
         else
        {
             if (contentType ==  " js ")
            {
                contentType =  " type/javascript ";
            }
             else  if (contentType ==  " css ")
            {
                contentType =  " text/css ";
            }
             else
            {
                contentType =  " text/plain ";
            }
        }
         bool isCompressed = DO_GZIP && CanGZip(context.Request);

        UTF8Encoding encoding =  new UTF8Encoding( false);

         if (!WriteFromCache(context, setName, isCompressed, contentType))
        {
            System.Collections.Generic.List< string> dependencyFiles =  new System.Collections.Generic.List< string>();
             using (MemoryStream memoryStream =  new MemoryStream( 5000))
            {
                 using (Stream writer = isCompressed ?
                    (Stream)( new GZipStream(memoryStream, CompressionMode.Compress)) :
                    memoryStream)
                {
                     string[] fileNames = setName.Split( new  char[] {  ' , ' }, StringSplitOptions.RemoveEmptyEntries);
                     foreach ( string fileName  in fileNames)
                    {
                         byte[] fileBytes = GetFileBytes(contentType, context, fileName.Trim(), encoding, dependencyFiles);
                        writer.Write(fileBytes,  0, fileBytes.Length);
                    }
                    writer.Close();
                }
                 byte[] responseBytes = memoryStream.ToArray();
                context.Cache.Insert(GetCacheKey(setName, isCompressed), responseBytes,  new CacheDependency(dependencyFiles.ToArray()), System.Web.Caching.Cache.NoAbsoluteExpiration, CACHE_DURATION);
                WriteBytes(responseBytes, context, isCompressed, contentType);
            }
        }
    }

     private  static  byte[] GetFileBytes( string contentType, HttpContext context,  string virtualPath, Encoding encoding, System.Collections.Generic.List< string> depencesFile)
    {
         if (virtualPath.StartsWith( " http:// ", StringComparison.InvariantCultureIgnoreCase))
        {
             using (WebClient client =  new WebClient())
            {
                 return client.DownloadData(virtualPath);
            }
        }
         else
        {
             if (!virtualPath.StartsWith( " ~/ ", StringComparison.InvariantCultureIgnoreCase))
            {
                 if (contentType ==  " text/css ")
                {
                    virtualPath = CSSPathPre + virtualPath;
                }
                 else  if (contentType ==  " type/javascript ")
                {
                    virtualPath = JSPathPre + virtualPath;
                }
            }
             string physicalPath = context.Server.MapPath(virtualPath);
            depencesFile.Add(physicalPath);
             byte[] bytes = File.ReadAllBytes(physicalPath);
             return bytes;
        }
    }

     private  static  bool WriteFromCache(HttpContext context,  string setName, bool isCompressed,  string contentType)
    {
         byte[] responseBytes = context.Cache[GetCacheKey(setName, isCompressed)]  as  byte[];
         if ( null == responseBytes ||  0 == responseBytes.Length)  return  false;
        WriteBytes(responseBytes, context, isCompressed, contentType);
         return  true;
    }

     private  static  void WriteBytes( byte[] bytes, HttpContext context, bool isCompressed,  string contentType)
    {
        HttpResponse response = context.Response;
        response.AppendHeader( " Content-Length ", bytes.Length.ToString());
        response.ContentType = contentType;
         if (isCompressed) response.AppendHeader( " Content-Encoding "" gzip ");
        context.Response.Cache.SetCacheability(HttpCacheability.Public);
        context.Response.Cache.SetExpires(DateTime.Now.Add(CACHE_DURATION));
        context.Response.Cache.SetMaxAge(CACHE_DURATION);
        context.Response.Cache.AppendCacheExtension( " must-revalidate, proxy-revalidate ");
        response.OutputStream.Write(bytes,  0, bytes.Length);
        response.Flush();
    }

     private  static  bool CanGZip(HttpRequest request)
    {
         string acceptEncoding = request.Headers[ " Accept-Encoding "];
         if (! string.IsNullOrEmpty(acceptEncoding) && (acceptEncoding.Contains( " gzip ") || acceptEncoding.Contains( " deflate ")))
             return  true;
         return  false;
    }

     private  static  string GetCacheKey( string setName,  bool isCompressed)
    {
         return  " HttpCombiner. " + setName +  " . " + isCompressed;
    }

     public  bool IsReusable
    {
         get
        {
             return  true;
        }
    }
     #endregion

 

 

你可能感兴趣的:(http)