发表于2014-07-18 21:36:37
上一篇我们介绍了网站在线安装的下载功能,压缩包下载后,就可以进行解压了,但是考虑到安装文件的精减问题,在这里我使用了Gizp算法。
本文介绍如何使用Gzip进行文件的压缩与解压。
在之前,我们来讲下规则与原理。我们将所有的文件与文件夹信息,统一放到一个字典对象中,以文件路径做为字典的Key,为了方便区分文件与文件夹,在路径的第一个字符用来标识类型,文件夹为0,文件为1。
因为压缩功能只是方便我们自己打包发布版本,不需要用户下载使用,所以我们需要新开一个页面(也可以建一个windows程序,用来以后统一打包发布)
在这里,我们新建一个aspx页,命名为FilesCreateZip.aspx,代码如下:
<%@ Page Language="C#" AutoEventWireup="true" %> protected void Page_Load(object sender, EventArgs e) { CreateSetupZip(Server.MapPath("~/"), Server.MapPath("~/setup.zip")); Response.Write("success"); } public void CreateSetupZip(string basePath, string savePath) { System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(basePath); System.Collections.Generic.Dictionary<string, object> dic = GetAllList(di, di.FullName); CreateCompressFile(SerializeBinary(dic), savePath); } public byte[] SerializeBinary(object request) { System.Runtime.Serialization.Formatters.Binary.BinaryFormatter serializer = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); using (System.IO.MemoryStream memStream = new System.IO.MemoryStream()) { serializer.Serialize(memStream, request); return memStream.ToArray(); } } private System.Collections.Generic.Dictionary<string, object> GetAllList(System.IO.DirectoryInfo di, string basePath) { System.Collections.Generic.Dictionary<string, object> dic = new System.Collections.Generic.Dictionary<string, object>(); foreach (System.IO.DirectoryInfo node in di.GetDirectories()) { dic["0" + node.FullName.Replace(basePath, null)] = GetAllList(node, basePath); } foreach (System.IO.FileInfo node in di.GetFiles()) { dic["1" + node.FullName.Replace(basePath, null)] = System.IO.File.ReadAllBytes(node.FullName); } return dic; } private void CreateCompressFile(byte[] bytes, string destinationName) { using (System.IO.Stream destination = new System.IO.FileStream(destinationName, System.IO.FileMode.Create, System.IO.FileAccess.Write)) { using (System.IO.Compression.GZipStream output = new System.IO.Compression.GZipStream(destination, System.IO.Compression.CompressionMode.Compress)) { output.Write(bytes, 0, bytes.Length); } } } </script>
在Page_Load方法中的CreateSetupZip(Server.MapPath("~/"), Server.MapPath("~/setup.zip"));第一个参数表示打包的路径,第二个参数是打包文件的保存路径,实际使用中,请调整这二个参数。
压缩包做后,我们就可以现实现解压方法了,解压方法和下载方法放在同一个页即可。代码如下:
至此,我们的ownloadAndDeCompress.aspx页面就已经处理完了,下一篇,我将讲解如何将此文件嵌入另一个页面,来实现完整的在线安装功能。public void DeCompress(string fileName, string dirPath) { using (System.IO.Stream source = System.IO.File.OpenRead(fileName)) { using (System.IO.Stream destination = new System.IO.MemoryStream()) { using (System.IO.Compression.GZipStream input = new System.IO.Compression.GZipStream(source, System.IO.Compression.CompressionMode.Decompress, true)) { byte[] bytes = new byte[4096]; int n; while ((n = input.Read(bytes, 0, bytes.Length)) != 0) { destination.Write(bytes, 0, n); } } destination.Flush(); destination.Position = 0; DeSerializeFiles(destination, dirPath); } } } private void DeSerializeFiles(System.IO.Stream s, string dirPath) { System.Runtime.Serialization.Formatters.Binary.BinaryFormatter b = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); System.Collections.Generic.Dictionary<string, object> list = (System.Collections.Generic.Dictionary<string, object>)b.Deserialize(s); DeFiles(list, dirPath); } private void DeFiles(System.Collections.Generic.Dictionary<string, object> list, string dirPath) { foreach (System.Collections.Generic.KeyValuePair<string, object> n in list) { string newName = string.Concat(dirPath, n.Key.Remove(0, 1)); if (n.Key[0] == '0') { System.IO.Directory.CreateDirectory(newName); if (n.Value != null) { DeFiles((System.Collections.Generic.Dictionary<string, object>)n.Value, dirPath); } } else { using (System.IO.FileStream fs = new System.IO.FileStream(newName, System.IO.FileMode.Create, System.IO.FileAccess.Write)) { byte[] bytes = (byte[])n.Value; fs.Write(bytes, 0, bytes.Length); fs.Close(); } } } }