昨晚上写了一篇"压缩ASP.NET中的ViewState"的文章,大家都对这种方式是否会带来性能上消耗的问题比较关心. 今天双鱼座网友的留言写的挺好的: 晚上借用加班的时间按双鱼座网友的方案对代码进行了一些改动,可以设置当ViewState为多大时才启用压缩,和压缩比率的设置. using System; using System.Web.UI; using System.IO; using ICSharpCode.SharpZipLib.Zip.Compression; namespace MSPlus.Web.UI { /**//// <summary> /// PageClass 的摘要说明。 /// </summary> public class Page : System.Web.UI.Page { /**//// <summary> /// 设定序列化后的字符串长度为多少后启用压缩 /// </summary> private static Int32 LimitLength = 1096; /**//// <summary> /// 设定压缩比率,压缩比率越高性消耗也将增大 /// </summary> private static Int32 ZipLevel = ICSharpCode.SharpZipLib.Zip.Compression.Deflater.BEST_COMPRESSION; /**//// <summary> /// 重写保存页的所有视图状态信息 /// </summary> /// <param name="pViewState">要在其中存储视图状态信息的对象</param> protected override void SavePageStateToPersistenceMedium(Object pViewState) { //实现一个用于将信息写入字符串的 TextWriter StringWriter mWriter = new StringWriter(); //序列化 Web 窗体页的视图状态 LosFormatter mFormat = new LosFormatter(); //将有限对象序列化 (LOS) 格式化的对象转换为视图状态值 mFormat.Serialize(mWriter, pViewState); //将序列化对象转成Base64字符串 String vStateStr = mWriter.ToString(); //设置是否启用了加密方式,默认情况下为不启用 Boolean mUseZip = false; //判断序列化对象的字符串长度是否超出定义的长度界限 if(vStateStr.Length > LimitLength) { //对于长度超出阶线的进行加密,同时将状态设为加密方式 mUseZip = true; Byte[] pBytes = Compress(vStateStr); //将字节数组转换为Base64字符串 vStateStr = System.Convert.ToBase64String(pBytes); } //注册在页面储存ViewState状态的隐藏文本框,并将内容写入这个文本框 RegisterHiddenField("__MSPVSTATE", vStateStr); //注册在页面储存是否启用压缩状态的文本框,并将启用状态写入这个文本框 RegisterHiddenField("__MSPVSTATE_ZIP", mUseZip.ToString().ToLower()); } /**//// <summary> /// 对字符串进行压缩 /// </summary> /// <param name="pViewState">ViewState字符串</param> /// <returns>返回流的字节数组</returns> public static Byte[] Compress(String pViewState) { //将存储状态的Base64字串转换为字节数组 Byte[] pBytes = System.Convert.FromBase64String(pViewState); //创建支持内存存储的流 MemoryStream mMemory = new MemoryStream(); Deflater mDeflater = new Deflater(ZipLevel); ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream mStream = new ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream(mMemory,mDeflater,131072); mStream.Write(pBytes,0,pBytes.Length); mStream.Close(); return mMemory.ToArray(); } /**//// <summary> /// 重写将所有保存的视图状态信息加载到页面对象 /// </summary> /// <returns>保存的视图状态</returns> protected override Object LoadPageStateFromPersistenceMedium() { //使用Request方法获取序列化的ViewState字符串 String mViewState = this.Request.Form.Get("__MSPVSTATE"); //使和Request方法获取当前的ViewState是否启用了压缩 String mViewStateZip = this.Request.Form.Get("__MSPVSTATE_ZIP"); Byte[] pBytes; if(mViewStateZip == "true") { pBytes = DeCompress(mViewState); } else { //将ViewState的Base64字符串转换成字节 pBytes = System.Convert.FromBase64String(mViewState); } //序列化 Web 窗体页的视图状态 LosFormatter mFormat = new LosFormatter(); //将指定的视图状态值转换为有限对象序列化 (LOS) 格式化的对象 return mFormat.Deserialize(System.Convert.ToBase64String(pBytes)); } /**//// <summary> /// 解压缩ViewState字符串 /// </summary> /// <param name="pViewState">ViewState字符串</param> /// <returns>返回流的字节数组</returns> public static Byte[] DeCompress(String pViewState) { //将Base64字符串转换为字节数组 Byte[] pBytes = System.Convert.FromBase64String(pViewState); ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream mStream = new ICSharpCode.SharpZipLib.Zip.Compression.Streams.InflaterInputStream(new MemoryStream(pBytes)); //创建支持内存存储的流 MemoryStream mMemory = new MemoryStream(); Int32 mSize; Byte[] mWriteData = new Byte[4096]; while(true) { mSize = mStream.Read(mWriteData, 0, mWriteData.Length); if (mSize > 0) { mMemory.Write(mWriteData, 0, mSize); } else { break; } } mStream.Close(); return mMemory.ToArray(); } } } 其中压缩组件用的是SharpZipLib |
|