【转】C#执行rar,zip文件压缩的几种方法及我遇到的坑总结

工作项目中需要用到zip压缩解压缩文件,一开始看上了Ionic.Zip.dll这个类库,操作方便,写法简单

对应有个ziphelper类

 

using Ionic.Zip;

    public static class ZipHelper
    {

        public static void UnZip(string zipPath, string outPath)
        {
            try
            {
                using (ZipFile zip = ZipFile.Read(zipPath))
                {
                    foreach (ZipEntry entry in zip)
                    {
                        entry.Extract(outPath, ExtractExistingFileAction.OverwriteSilently);
                    }
                }
            }
            catch(Exception ex)
            {
                File.WriteAllText(System.Web.HttpContext.Current.Server.MapPath("/1.txt"),ex.Message + "\r\n" + ex.StackTrace);
            }
        }
        /// 
        /// 递归子目录时调用
        /// ZipHelper.Zip(files, path + model.CName + "/" + siteid + ".zip", path + model.CName + "/");
       /// ZipHelper.ZipDir( path + model.CName + "/" + siteid + ".zip", path + model.CName + "/", path + model.CName + "/");
        /// 
        /// 要保存的文件名
        /// 要遍历的目录
        /// 压缩包起始目录结尾必须反斜杠

        public static void ZipDir(string savefileName, string childPath, string startPath)
        {
            DirectoryInfo di = new DirectoryInfo(childPath);
            if (di.GetDirectories().Length > 0) //有子目录
            {
                foreach (DirectoryInfo dirs in di.GetDirectories())
                {
                    string[] n = Directory.GetFiles(dirs.FullName, "*");
                    Zip(n, savefileName, startPath);
                    ZipDir(savefileName, dirs.FullName, startPath);
                }
            }
        }
        /// 
        /// 压缩zip
        /// 
        /// 文件路径集合
        /// 想要压成zip的文件名
        /// 文件夹起始目录结尾必须反斜杠
        public static void Zip(string[] fileToZips, string zipedFile,string fileDirStart)
        {
            using (ZipFile zip = new ZipFile(zipedFile, Encoding.UTF8))
            {
                foreach (string fileToZip in fileToZips)
                { 
                    string fileName = fileToZip.Substring(fileToZip.LastIndexOf("\\", StringComparison.Ordinal) + 1);
                    zip.AddFile(fileToZip, fileToZip.Replace(fileDirStart, "").Replace(fileName, ""));
                    //zip.AddFile(fileToZip, fileToZip.Replace(fileDirStart, "").Replace(fileName, ""));
                    //using (var fs = new FileStream(fileToZip, FileMode.Open, FileAccess.ReadWrite))
                    //{
                    //    var buffer = new byte[fs.Length];
                    //    fs.Read(buffer, 0, buffer.Length);
                    //    string fileName = fileToZip.Substring(fileToZip.LastIndexOf("\\", StringComparison.Ordinal) + 1);
                    //    zip.AddEntry(fileName, buffer);
                    //}
                }
                zip.Save();
            }
        }

        public static void ZipOneFile(string from, string zipedFile, string to)
        {
            using (ZipFile zip = new ZipFile(zipedFile, Encoding.UTF8))
            {
                zip.AddFile(from, to);
                zip.Save();
            }
        }

    }

使用方法:

    string path = Request.MapPath("/");
    string[] files = Directory.GetFiles(path, "*");
    ZipHelper.Zip(files, path + "1.zip", path);//压缩path下的所有文件
    ZipHelper.ZipDir(path + "1.zip", path, path);//递归压缩path下的文件夹里的文件
    ZipHelper.UnZip(Server.MapPath("/") + "lgs.zip", Server.MapPath("/"));//解压缩

正常情况下这个使用是不会有问题的,我一直在用,不过我遇到了一个变态问题,服务器端为了安全需求,禁用了File.Move方法,然后这个类库解压缩时采用了重命名方案,然后很尴尬的执行失败,困扰了我大半年时间,一直不知道原因,不过因为这个bug时隐时现,在 个别服务器上出现,所以一直没有解决,总算最近发现问题了。

于是我想干脆不用zip压缩了,直接调用服务器上的WinRar,这个问题显而易见,服务器如果没有安装,或者不给权限同样无法使用,我就遇到了,不过给个操作方法代码

public class WinRarHelper
{
    public WinRarHelper()
    {

    }

    static WinRarHelper()
    {
        //判断是否安装了WinRar.exe
        RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\WinRAR.exe");
        _existSetupWinRar = !string.IsNullOrEmpty(key.GetValue(string.Empty).ToString());

        //获取WinRar.exe路径
        _winRarPath = key.GetValue(string.Empty).ToString();
    }

    static bool _existSetupWinRar;
    /// 
    /// 获取是否安装了WinRar的标识
    /// 
    public static bool ExistSetupWinRar
    {
        get { return _existSetupWinRar; }
    }

    static string _winRarPath;
    /// 
    /// 获取WinRar.exe路径
    /// 
    public static string WinRarPath
    {
        get { return _winRarPath; }
    }

    #region 压缩到.rar,这个方法针对目录压缩
    /// 
    /// 压缩到.rar,这个方法针对目录压缩
    /// 
    /// 输入目录
    /// 输出目录
    /// 输出文件名
    public static void CompressRar(string intputPath, string outputPath, string outputFileName)
    {
        //rar 执行时的命令、参数
        string rarCmd;
        //启动进程的参数
        ProcessStartInfo processStartInfo = new ProcessStartInfo();
        //进程对象
        Process process = new Process();
        try
        {
            if (!ExistSetupWinRar)
            {
                throw new ArgumentException("请确认服务器上已安装WinRar应用!");
            }
            //判断输入目录是否存在
            if (!Directory.Exists(intputPath))
            {
                throw new ArgumentException("指定的要压缩目录不存在!");
            }
            //命令参数  uxinxin修正参数压缩文件到当前目录,而不是从盘符开始
            rarCmd = " a " + outputFileName + " " + "./" + " -r";
            //rarCmd = " a " + outputFileName + " " + outputPath + " -r";
            //创建启动进程的参数
            //指定启动文件名
            processStartInfo.FileName = WinRarPath;
            //指定启动该文件时的命令、参数
            processStartInfo.Arguments = rarCmd;
            //指定启动窗口模式:隐藏
            processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            //指定压缩后到达路径
            processStartInfo.WorkingDirectory = outputPath;
            //创建进程对象
            
            //指定进程对象启动信息对象
            process.StartInfo = processStartInfo;
            //启动进程
            process.Start();
            //指定进程自行退行为止
            process.WaitForExit();
            //Uxinxin增加的清理关闭,不知道是否有效
            process.Close();
            process.Dispose();
        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {
            process.Close();
            process.Dispose();

        }
    }
    #endregion

    #region 解压.rar
    /// 
    /// 解压.rar
    /// 
    /// 输入.rar
    /// 输出目录
    public static void UnCompressRar(string inputRarFileName, string outputPath)
    {
        //rar 执行时的命令、参数
        string rarCmd;
        //启动进程的参数
        ProcessStartInfo processStartInfo = new ProcessStartInfo();
        //进程对象
        Process process = new Process();
        try
        {
            if (!ExistSetupWinRar)
            {
                throw new ArgumentException("请确认服务器上已安装WinRar应用!");
            }
            //如果压缩到目标路径不存在
            if (!Directory.Exists(outputPath))
            {
                //创建压缩到目标路径
                Directory.CreateDirectory(outputPath);
            }
            rarCmd = "x " + inputRarFileName + " " + outputPath + " -y";


            processStartInfo.FileName = WinRarPath;
            processStartInfo.Arguments = rarCmd;
            processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            processStartInfo.WorkingDirectory = outputPath;


            process.StartInfo = processStartInfo;
            process.Start();
            process.WaitForExit();
            process.Close();
            process.Dispose();
        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {
            process.Close();
            process.Dispose();
        }
    }
    #endregion

    #region 将传入的文件列表压缩到指定的目录下
    /// 
    /// 将传入的文件列表压缩到指定的目录下
    /// 
    /// 要压缩的文件路径列表
    /// 压缩文件存放路径
    /// 压缩文件名(全名)
    public static void CompressFilesToRar(List sourceFilesPaths, string compressFileSavePath, string compressFileName)
    {
        //rar 执行时的命令、参数
        string rarCmd;
        //启动进程的参数
        ProcessStartInfo processStartInfo = new ProcessStartInfo();
        //创建进程对象
        //进程对象
        Process process = new Process();
        try
        {
            if (!ExistSetupWinRar)
            {
                throw new ArgumentException("Not setuping the winRar, you can Compress.make sure setuped winRar.");
            }
            //判断输入文件列表是否为空
            if (sourceFilesPaths == null || sourceFilesPaths.Count < 1)
            {
                throw new ArgumentException("CompressRar'arge : sourceFilesPaths cannot be null.");
            }
            rarCmd = " a -ep1 -ap " + compressFileName;
                //-ep1 -ap表示压缩时不保留原有文件的路径,都压缩到压缩包中即可,调用winrar命令内容可以参考我转载的另一篇文章:教你如何在DOS(cmd)下使用WinRAR压缩文件
            foreach (object filePath in sourceFilesPaths)
            {
                rarCmd += " " + filePath.ToString(); //每个文件路径要与其他的文件用空格隔开
            }
            //rarCmd += " -r";
            //创建启动进程的参数

            //指定启动文件名
            processStartInfo.FileName = WinRarPath;
            //指定启动该文件时的命令、参数
            processStartInfo.Arguments = rarCmd;
            //指定启动窗口模式:隐藏
            processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            //指定压缩后到达路径
            processStartInfo.WorkingDirectory = compressFileSavePath;

            //指定进程对象启动信息对象
            process.StartInfo = processStartInfo;
            //启动进程
            process.Start();
            //指定进程自行退行为止
            process.WaitForExit();
            process.Close();
            process.Dispose();
        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {
            process.Close();
            process.Dispose();
        }
    }
    #endregion
}

调用方法:

if (WinRarHelper.ExistSetupWinRar)
        {
            try
            {
                WinRarHelper.CompressRar(Server.MapPath("/"), Server.MapPath("/"), "1.zip");
                Response.Write("压缩完成!" + DateTime.Now);
            }
            catch (Win32Exception e1)
            {
                Response.Write(e1.Message + "
" + "服务器端禁止是我们网站使用WinRar应用执行!
");
            }
            catch (Exception e1)
            {
                Response.Write(e1.Message + "
" + e1.StackTrace);
            }

        if (WinRarHelper.ExistSetupWinRar)
        {
            try
            {
                WinRarHelper.UnCompressRar(Server.MapPath("/") + "lgs.zip", Server.MapPath("/"));
                Response.Write("解压缩完成!" + DateTime.Now);
            }
            catch (Win32Exception e1)
            {
                Response.Write(e1.Message + "
" + "服务器端禁止是我们网站使用WinRar应用执行!
");

            }
            catch (Exception e1)
            {
                Response.Write(e1.Message);
            }
        }

最后我找到了一个解压的时候不用重命名方法的,还好服务器对解压没限制

ICSharpCode.SharpZipLib.dll  用到这个文件

参考来自http://www.cnblogs.com/yuangang/p/5581391.html

具体我也不写了,就看参考网站吧,我也没改代码,不错,记录一下,花了我整整一天折腾这玩意儿!

你可能感兴趣的:(csharp)