Asp.Net实现在线网站安装(中)——压缩与解压

翅膀的初衷

发表于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"));第一个参数表示打包的路径,第二个参数是打包文件的保存路径,实际使用中,请调整这二个参数。

压缩包做后,我们就可以现实现解压方法了,解压方法和下载方法放在同一个页即可。代码如下:

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(); } } } }
至此,我们的ownloadAndDeCompress.aspx页面就已经处理完了,下一篇,我将讲解如何将此文件嵌入另一个页面,来实现完整的在线安装功能。