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

作者:翅膀的初衷 来源:本站原创 发布时间:2014-07-18 查看数:54741

上一篇我们介绍了网站在线安装的下载功能,压缩包下载后,就可以进行解压了,但是考虑到安装文件的精减问题,在这里我使用了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页面就已经处理完了,下一篇,我将讲解如何将此文件嵌入另一个页面,来实现完整的在线安装功能。