重写PageStatePersister属性 自定义压缩方法来减小ViewState大小来优化页面加载时间

//在正常情况下,页面都会自动调用默认的LosFormatter来压缩ViewState. 但是我们可以实现PageStatePersister类。
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.IO;
using System.IO.Compression;
/// <summary>
/// CompressPageStatePersister 的摘要说明
/// </summary>
public class CompressPageStatePersister:PageStatePersister
{
    
//页面状态保存在页面中的字段名
    private const string STATEKEY = "____VIEWSTATE";

    
public CompressPageStatePersister(Page page) : base(page) { }

    
public override void Load()
    {
        
//取得保存到客户端的状态内容
        string postbackState = Page.Request.Form[STATEKEY];
        
if (!string.IsNullOrEmpty(postbackState))
        {
            
//解压,反序列化状态,
            
//ASP.NET2.0中的页面状态包括视图状态和控件状态两部分
            Pair statePair = (Pair)GZipCompress.Decompress(postbackState);
            
if (!Page.EnableViewState)
            {
                ViewState 
= null;
            }
            
else
            {
                ViewState 
= statePair.First;
            }
            ControlState 
= statePair.Second;

        }
    }

    
public override void Save()
    {
        
if (!Page.EnableViewState)
        {
            ViewState 
= null;
        }
        
if (ViewState != null || ControlState != null)
        {
            
string stateString;
            Pair statePair 
= new Pair(ViewState, ControlState);
            
//序列化并压缩状态
            stateString = GZipCompress.Compress(statePair);
            Page.ClientScript.RegisterHiddenField(STATEKEY, stateString);
        }
    }
}









public class GZipTest
{
    
public static int ReadAllBytesFromStream(Stream stream, byte[] buffer)
    {
        
// Use this method is used to read all bytes from a stream.
        int offset = 0;
        
int totalCount = 0;
        
while (true)
        {
            
int bytesRead = stream.Read(buffer, offset, 100);
            
if (bytesRead <= 0)
            {
                
break;
            }
            offset 
+= bytesRead;
            totalCount 
+= bytesRead;
        }
        
return totalCount;
    }

    
public static bool CompareData(byte[] buf1, int len1, byte[] buf2, int len2)
    {
        
// Use this method to compare data from two different buffers.
        if (len1 != len2)
        {
            Console.WriteLine(
"Number of bytes in two buffer are different {0}:{1}", len1, len2);
            
return false;
        }

        
for (int i = 0; i < len1; i++)
        {
            
if (buf1[i] != buf2[i])
            {
                Console.WriteLine(
"byte {0} is different {1}|{2}", i, buf1[i], buf2[i]);
                
return false;
            }
        }
        Console.WriteLine(
"All bytes compare.");
        
return true;
    }

    
public static void GZipCompressDecompress(string filename)
    {
        Console.WriteLine(
"Test compression and decompression on file {0}", filename);
        FileStream infile;
        
try
        {
            
// Open the file as a FileStream object.
            infile = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
            
byte[] buffer = new byte[infile.Length];
            
// Read the file to ensure it is readable.
            int count = infile.Read(buffer, 0, buffer.Length);
            
if (count != buffer.Length)
            {
                infile.Close();
                Console.WriteLine(
"Test Failed: Unable to read data from file");
                
return;
            }
            infile.Close();
            MemoryStream ms 
= new MemoryStream();
            
// Use the newly created memory stream for the compressed data.
            GZipStream compressedzipStream = new GZipStream(ms, CompressionMode.Compress, true);
            Console.WriteLine(
"Compression");
            compressedzipStream.Write(buffer, 
0, buffer.Length);
            
// Close the stream.
            compressedzipStream.Close();
            Console.WriteLine(
"Original size: {0}, Compressed size: {1}", buffer.Length, ms.Length);

            
// Reset the memory stream position to begin decompression.
            ms.Position = 0;
            GZipStream zipStream 
= new GZipStream(ms, CompressionMode.Decompress);
            Console.WriteLine(
"Decompression");
            
byte[] decompressedBuffer = new byte[buffer.Length + 100];
            
// Use the ReadAllBytesFromStream to read the stream.
            int totalCount = GZipTest.ReadAllBytesFromStream(zipStream, decompressedBuffer);
            Console.WriteLine(
"Decompressed {0} bytes", totalCount);

            
if (!GZipTest.CompareData(buffer, buffer.Length, decompressedBuffer, totalCount))
            {
                Console.WriteLine(
"Error. The two buffers did not compare.");
            }
            zipStream.Close();
        } 
// end try
        catch (InvalidDataException)
        {
            Console.WriteLine(
"Error: The file being read contains invalid data.");
        }
        
catch (FileNotFoundException)
        {
            Console.WriteLine(
"Error:The file specified was not found.");
        }
        
catch (ArgumentException)
        {
            Console.WriteLine(
"Error: path is a zero-length string, contains only white space, or contains one or more invalid characters");
        }
        
catch (PathTooLongException)
        {
            Console.WriteLine(
"Error: The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.");
        }
        
catch (DirectoryNotFoundException)
        {
            Console.WriteLine(
"Error: The specified path is invalid, such as being on an unmapped drive.");
        }
        
catch (IOException)
        {
            Console.WriteLine(
"Error: An I/O error occurred while opening the file.");
        }
        
catch (UnauthorizedAccessException)
        {
            Console.WriteLine(
"Error: path specified a file that is read-only, the path is a directory, or caller does not have the required permissions.");
        }
        
catch (IndexOutOfRangeException)
        {
            Console.WriteLine(
"Error: You must provide parameters for MyGZIP.");
        }
    }
    
public static void Main(string[] args)
    {
        
string usageText = "Usage: MYGZIP <inputfilename>";
        
//If no file name is specified, write usage text.
        if (args.Length == 0)
        {
            Console.WriteLine(usageText);
        }
        
else
        {
            
if (File.Exists(args[0]))
                GZipCompressDecompress(args[
0]);
        }
    }
}

//GzipCompress

using System;
using System.IO;
using System.IO.Compression;
using System.Web.UI;

/// <summary>
/// GZipCompress 的摘要说明
/// </summary>
public class GZipCompress
{
    
//序列化工具,LosFormatter是页面默认的序列器
    private static LosFormatter _formatter = new LosFormatter();
    
/// <summary>
    
/// 解压并反序列化状态内容
    
/// </summary>
    
/// <param name="stateString">从客户端取回的页面状态字符串</param>
    
/// <returns>还原后的页面状态Pair对象</returns>
    public static object Decompress(string stateString)
    {
        
//先把取回的状态字符串转回压缩后的数组
        byte[] buffer = Convert.FromBase64String(stateString);
        
//解压
        MemoryStream ms = new MemoryStream(buffer);
        GZipStream zipStream 
= new GZipStream(ms, CompressionMode.Decompress);
        MemoryStream msReader 
= new MemoryStream();
        buffer 
= new byte[0x1000];
        
while (true)
        {
            
int read = zipStream.Read(buffer, 0, buffer.Length);
            
if (read <= 0)
            {
                
break;
            }
            msReader.Write(buffer, 
0, read);
        }
        zipStream.Close();
        ms.Close();
        msReader.Position 
= 0;
        buffer 
= msReader.ToArray();
        stateString 
= Convert.ToBase64String(buffer);
        
//反序列化
        return _formatter.Deserialize(stateString);
    }
    
/// <summary>
    
/// 序列化并压缩状态内容
    
/// </summary>
    
/// <param name="state">页面状态</param>
    
/// <returns>结果字符串</returns>
    public static string Compress(object state)
    {
        StringWriter writer 
= new StringWriter();
        
//序列化状态
        _formatter.Serialize(writer, state);
        
//取得序列化结果
        string stateString = writer.ToString();
        writer.Close();        
        
//压缩序列化状态
        byte[] buffer = Convert.FromBase64String(stateString);
        MemoryStream ms 
= new MemoryStream();
        GZipStream zipStream 
= new GZipStream(ms, CompressionMode.Compress, true);
        zipStream.Write(buffer, 
0, buffer.Length);
        zipStream.Close();
        buffer 
= new byte[ms.Length];
        ms.Position 
= 0;
        ms.Read(buffer, 
0, buffer.Length);
        ms.Close();
        
//将压缩结果转成Base64字符串,以便存到页面中
        stateString = Convert.ToBase64String(buffer);
        
return stateString;
    }
}

 

//测试
public partial class Pages_Default : System.Web.UI.Page
{
    
#region
    CompressPageStatePersister _pageStatePersister 
= null;
    
protected override PageStatePersister PageStatePersister
    {
        
get
        {
            
if (_pageStatePersister == null)
            {
                _pageStatePersister 
= new CompressPageStatePersister(this);
            }
            
return _pageStatePersister;
        }
    }
    
#endregion

    
protected void Page_Load(object sender, EventArgs e)
    {
        GridView1.DataBind();
    }
}

posted on 2009-09-29 18:14  博览潇湘  阅读(683)  评论(1编辑  收藏  举报

导航