Asp.net压缩网站中的文件

为了说明自定义虚拟路径,这里弄个示例,仅仅用一个压缩包存放一个网站的多个文件。

  这个东西是要需要通过实现3个抽象类来实现:

  • System.Web.Hosting.VirtualPathProvider;
  • System.Web.Hosting.VirtualDirectory;
  • System.Web.Hosting.VirtualFile;

  因为,我真的不知道如何去缩减,代码比较多。首先新建一个Web项目,然后添加如下3个类:

  1、虚拟目录提供者类:

 
    public class ZipVirtualPathProvider : System.Web.Hosting.VirtualPathProvider
    {
        private string fileRootPath;
        private string virtualRootPath;
        private ZipVirtualDirectory root;

        public ZipVirtualPathProvider()
        {
            this.fileRootPath = HttpRuntime.AppDomainAppPath;
            this.virtualRootPath = HttpRuntime.AppDomainAppVirtualPath + "/";
            string path = string.Format("{0}App_Data\\test.zip", fileRootPath);
            using (ZipFile zipFile = new ZipFile(path))
            {
                // 创建根目录
                this.root = new ZipVirtualDirectory(virtualRootPath);
                foreach (ICSharpCode.SharpZipLib.Zip.ZipEntry entry in zipFile)
                {
                    string name = string.Format("{0}{1}", this.virtualRootPath, entry.Name);
                    VirtualDirectory parent = GetParentDirectory(name);
                    ZipVirtualDirectory zipParent = parent as ZipVirtualDirectory;
                    System.Web.Hosting.VirtualFileBase vfb;
                    if (entry.IsDirectory)
                    {
                        vfb = new ZipVirtualDirectory(name);
                    }
                    else
                    {
                        System.IO.Stream stream = zipFile.GetInputStream(entry);
                        int size = (int)entry.Size;
                        byte[] buffer = ReadAllBytes(stream, size);
                        vfb = new ZipVirtualFile(name, buffer);
                    }
                    zipParent.AddVirtualItem(vfb);
                }
            }
        }

        //寻找子目录所属的父目录 
        private VirtualDirectory GetParentDirectory(string virtualPath)
        {
            // 从根目录开始找,直到找不到为止,说明就是所属的父目录,加入父目录中
            VirtualDirectory root = this.root;
            while (true)
            {
                bool isContinue = false;
                foreach (VirtualDirectory dir in root.Directories)
                {
                    if (virtualPath.StartsWith(dir.VirtualPath))
                    {
                        root = dir;
                        isContinue = true;
                        break;
                    }
                }

                if (isContinue)
                    continue;

                // 如果都不是,那么,当前的  root 就是其父目录
                return root;
            }
        }

        //是否存在目录
        public override bool DirectoryExists(string virtualDir)
        {
            /// 从根目录开始递归寻找
            bool result = SearchDirectory(this.root, virtualDir);
            if (result)
            {
                return true;
            }
            return this.Previous.DirectoryExists(virtualDir);
        }

        //搜索目录
        private bool SearchDirectory(VirtualDirectory parent, string virtualDir)
        {
            if (parent.Name == virtualDir)
            {
                return true;
            }

            foreach (VirtualDirectory child in parent.Directories)
            {
                bool result = SearchDirectory(child, virtualDir);
                if (result)
                {
                    return true;
                }
            }
            return false;
        }

        //判断文件是否存在
        public override bool FileExists(string virtualPath)
        {

            //只检查压缩包的一级目录(有就有,没有就没有)
            foreach (VirtualFile file in this.root.Files)
            {
                if (file.Name.Replace("//", "/") == virtualPath)
                {
                    return true;
                }
            }
            return this.Previous.FileExists(virtualPath);
        }


        public override System.Web.Hosting.VirtualDirectory GetDirectory(string virtualDir)
        {
            VirtualDirectory dir = GetParentDirectory(virtualDir);
            // 不存在的话,找到父目录,存在的话,找到自己。
            bool exist = dir.VirtualPath == virtualDir;
            if (exist)
            {
                return dir;
            }
            return this.Previous.GetDirectory(virtualDir);
        }

        public override System.Web.Hosting.VirtualFile GetFile(string virtualPath)
        {
            //找到可能存在的目录
            VirtualDirectory dir = GetParentDirectory(virtualPath);

            // 遍历查找
            foreach (VirtualFile file in dir.Files)
            {
                if (file.VirtualPath == virtualPath)
                {
                    return file;
                }
            }

            return this.Previous.GetFile(virtualPath);
        }

        public override System.Web.Caching.CacheDependency GetCacheDependency(string virtualPath, System.Collections.IEnumerable virtualPathDependencies, DateTime utcStart)
        {
            // 由于采用了压缩文件,所以不生成缓存依赖对象
            return null;
        }

        private byte[] ReadAllBytes(System.IO.Stream stream, int size)
        {
            byte[] buffer = new byte[size];
            int count = stream.Read(buffer, 0, size);
            return buffer;
        }
    }
 

  虚拟目录与虚拟文件类:

 
    public class ZipVirtualDirectory : System.Web.Hosting.VirtualDirectory
    {
        //保存文件夹中包含的子项目的集合
        //包括文件和子目录
        private List<VirtualFileBase> items;
        private List<VirtualFile> files;
        private List<VirtualDirectory> directories;
        private string name;

        public override System.Collections.IEnumerable Files { get { return this.files; } }
        public override System.Collections.IEnumerable Children { get { return this.items; } }
        public override System.Collections.IEnumerable Directories { get { return directories; } }
        public override string Name { get { return base.Name; } }

        public ZipVirtualDirectory(string name) : base(name)
        {
            this.items = new List<VirtualFileBase>();
            this.directories = new List<VirtualDirectory>();
            this.files = new List<VirtualFile>();

            this.name = name;
        }

        // 在目录中增加一个项目
        public void AddVirtualItem(VirtualFileBase item)
        {
            this.items.Add(item);
            if (item.IsDirectory)
            {
                this.directories.Add(item as VirtualDirectory);
            }
            else
            {
                this.files.Add(item as VirtualFile);
            }
        }
    }

    public class ZipVirtualFile : System.Web.Hosting.VirtualFile
    {
        public override string Name { get {  return this.name; } }

        public override System.IO.Stream Open()
        {
            return new System.IO.MemoryStream(this.buffer);
        }

        private string name;
        private byte[] buffer;

        public ZipVirtualFile(string name, byte[] buffer) : base(name)
        {
            this.name = name;
            this.buffer = buffer;
        }
    }
 

  注册虚拟目录提供程序,在App_Code目录里面添加一个AppStart类:

 
    public class AppStart
    {
        public static void AppInitialize()
        {
            ZipVirtualPathProvider virtualPathProvider = new ZipVirtualPathProvider();
            System.Web.Hosting.HostingEnvironment.RegisterVirtualPathProvider(virtualPathProvider);
        }
    }
 

  然后新建一个zip压缩包,里面有如下两个页面:

  

  然后启动项目,打开路径:/test/1.html。

  

  网站程序中是不存在"test"这个目录的,但是自定义的虚拟目录将对此路径的访问映射到"test.zip"里面的1.html去了。这就是自定义虚拟路径提供器的强大之处。

posted on 2015-11-15 16:19  记性特差  阅读(381)  评论(0编辑  收藏  举报