缓存脚本和Css文件
Code
public class HttpCombiner : IHttpHandler
{
private const bool DO_GZIP = true;
private readonly static TimeSpan CACHE_DURATION = TimeSpan.FromDays(30);
public void ProcessRequest(HttpContext context)
{
HttpRequest request = context.Request;
//获取配置信息
string setName = request["s"] ?? string.Empty;
string contentType = request["t"] ?? string.Empty;
string version = request["v"] ?? string.Empty;
// 确认浏览器是否支持压缩输出
bool isCompressed = DO_GZIP && this.CanGZip(context.Request);
//以utf8向浏览器输出
UTF8Encoding encoding = new UTF8Encoding(false);
//如果缓存中存在该信息则直接从缓存中读否则下载文件并存入缓存
if (!this.WriteFromCache(context, setName, version, isCompressed, contentType))
{
using (MemoryStream memoryStream = new MemoryStream(5000))
{
using (Stream writer = isCompressed ?
(Stream)(new GZipStream(memoryStream, CompressionMode.Compress)) :
memoryStream)
{
//从配置文件中获取缓存文件列表
string setDefinition =
System.Configuration.ConfigurationManager.AppSettings[setName] ?? "";
string[] fileNames = setDefinition.Split(new char[] { ',' },
StringSplitOptions.RemoveEmptyEntries);
foreach (string fileName in fileNames)
{
byte[] fileBytes = this.GetFileBytes(context, fileName.Trim(), encoding);
writer.Write(fileBytes, 0, fileBytes.Length);
}
writer.Close();
}
//将信息写入缓存
byte[] responseBytes = memoryStream.ToArray();
context.Cache.Insert(GetCacheKey(setName, version, isCompressed),
responseBytes, null, System.Web.Caching.Cache.NoAbsoluteExpiration,
CACHE_DURATION);
//输出
this.WriteBytes(responseBytes, context, isCompressed, contentType);
}
}
}
private byte[] GetFileBytes(HttpContext context, string virtualPath, Encoding encoding)
{
if (virtualPath.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase))
{
using (WebClient client = new WebClient())
{
return client.DownloadData(virtualPath);
}
}
else
{
string physicalPath = context.Server.MapPath(virtualPath);
byte[] bytes = File.ReadAllBytes(physicalPath);
return bytes;
}
}
private bool WriteFromCache(HttpContext context, string setName, string version,
bool isCompressed, string contentType)
{
byte[] responseBytes = context.Cache[GetCacheKey(setName, version, isCompressed)] as byte[];
if (null == responseBytes || 0 == responseBytes.Length) return false;
this.WriteBytes(responseBytes, context, isCompressed, contentType);
return true;
}
private 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 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 string GetCacheKey(string setName, string version, bool isCompressed)
{
return "HttpCombiner." + setName + "." + version + "." + isCompressed;
}
public bool IsReusable
{
get
{
return true;
}
}
}
public class HttpCombiner : IHttpHandler
{
private const bool DO_GZIP = true;
private readonly static TimeSpan CACHE_DURATION = TimeSpan.FromDays(30);
public void ProcessRequest(HttpContext context)
{
HttpRequest request = context.Request;
//获取配置信息
string setName = request["s"] ?? string.Empty;
string contentType = request["t"] ?? string.Empty;
string version = request["v"] ?? string.Empty;
// 确认浏览器是否支持压缩输出
bool isCompressed = DO_GZIP && this.CanGZip(context.Request);
//以utf8向浏览器输出
UTF8Encoding encoding = new UTF8Encoding(false);
//如果缓存中存在该信息则直接从缓存中读否则下载文件并存入缓存
if (!this.WriteFromCache(context, setName, version, isCompressed, contentType))
{
using (MemoryStream memoryStream = new MemoryStream(5000))
{
using (Stream writer = isCompressed ?
(Stream)(new GZipStream(memoryStream, CompressionMode.Compress)) :
memoryStream)
{
//从配置文件中获取缓存文件列表
string setDefinition =
System.Configuration.ConfigurationManager.AppSettings[setName] ?? "";
string[] fileNames = setDefinition.Split(new char[] { ',' },
StringSplitOptions.RemoveEmptyEntries);
foreach (string fileName in fileNames)
{
byte[] fileBytes = this.GetFileBytes(context, fileName.Trim(), encoding);
writer.Write(fileBytes, 0, fileBytes.Length);
}
writer.Close();
}
//将信息写入缓存
byte[] responseBytes = memoryStream.ToArray();
context.Cache.Insert(GetCacheKey(setName, version, isCompressed),
responseBytes, null, System.Web.Caching.Cache.NoAbsoluteExpiration,
CACHE_DURATION);
//输出
this.WriteBytes(responseBytes, context, isCompressed, contentType);
}
}
}
private byte[] GetFileBytes(HttpContext context, string virtualPath, Encoding encoding)
{
if (virtualPath.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase))
{
using (WebClient client = new WebClient())
{
return client.DownloadData(virtualPath);
}
}
else
{
string physicalPath = context.Server.MapPath(virtualPath);
byte[] bytes = File.ReadAllBytes(physicalPath);
return bytes;
}
}
private bool WriteFromCache(HttpContext context, string setName, string version,
bool isCompressed, string contentType)
{
byte[] responseBytes = context.Cache[GetCacheKey(setName, version, isCompressed)] as byte[];
if (null == responseBytes || 0 == responseBytes.Length) return false;
this.WriteBytes(responseBytes, context, isCompressed, contentType);
return true;
}
private 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 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 string GetCacheKey(string setName, string version, bool isCompressed)
{
return "HttpCombiner." + setName + "." + version + "." + isCompressed;
}
public bool IsReusable
{
get
{
return true;
}
}
}
配置文件
Code
<add key="Set_Css" value="~/App_Themes/Default/Css1.css,~/App_Themes/Default/Css2.css"/>
<add key="Set_Javascript" value="~/Javascripts/Js1.js,~/Javascripts/Js2.js,http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"/>
<add key="Set_Css" value="~/App_Themes/Default/Css1.css,~/App_Themes/Default/Css2.css"/>
<add key="Set_Javascript" value="~/Javascripts/Js1.js,~/Javascripts/Js2.js,http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"/>
调用
Code
//指定Css文件
//<link type="text/css"
// rel="Stylesheet"
// href="HttpCombiner.ashx?s=Set_Css&t=text/css&v=1" />
//指定脚本文件
//<script
// type="text/javascript"
// src="HttpCombiner.ashx?s=Set_Javascript&t=type/javascript&v=2" >
//</script>
//指定Css文件
//<link type="text/css"
// rel="Stylesheet"
// href="HttpCombiner.ashx?s=Set_Css&t=text/css&v=1" />
//指定脚本文件
//<script
// type="text/javascript"
// src="HttpCombiner.ashx?s=Set_Javascript&t=type/javascript&v=2" >
//</script>