工作项目中需要用到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(ListsourceFilesPaths, 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
具体我也不写了,就看参考网站吧,我也没改代码,不错,记录一下,花了我整整一天折腾这玩意儿!