工作項目中需要用到zip壓縮解壓縮文件,一開始看上了Ionic.Zip.dll這個類庫,操作方便,寫法簡單
對應有個ziphelper類
1 using Ionic.Zip; 2 3 public static class ZipHelper 4 { 5 6 public static void UnZip(string zipPath, string outPath) 7 { 8 try 9 { 10 using (ZipFile zip = ZipFile.Read(zipPath)) 11 { 12 foreach (ZipEntry entry in zip) 13 { 14 entry.Extract(outPath, ExtractExistingFileAction.OverwriteSilently); 15 } 16 } 17 } 18 catch(Exception ex) 19 { 20 File.WriteAllText(System.Web.HttpContext.Current.Server.MapPath("/1.txt"),ex.Message + "\r\n" + ex.StackTrace); 21 } 22 } 23 /// <summary> 24 /// 遞歸子目錄時調用 25 /// ZipHelper.Zip(files, path + model.CName + "/" + siteid + ".zip", path + model.CName + "/"); 26 /// ZipHelper.ZipDir( path + model.CName + "/" + siteid + ".zip", path + model.CName + "/", path + model.CName + "/"); 27 /// </summary> 28 /// <param name="savefileName">要保存的文件名</param> 29 /// <param name="childPath">要遍歷的目錄</param> 30 /// <param name="startPath">壓縮包起始目錄結尾必須反斜杠</param> 31 32 public static void ZipDir(string savefileName, string childPath, string startPath) 33 { 34 DirectoryInfo di = new DirectoryInfo(childPath); 35 if (di.GetDirectories().Length > 0) //有子目錄 36 { 37 foreach (DirectoryInfo dirs in di.GetDirectories()) 38 { 39 string[] n = Directory.GetFiles(dirs.FullName, "*"); 40 Zip(n, savefileName, startPath); 41 ZipDir(savefileName, dirs.FullName, startPath); 42 } 43 } 44 } 45 /// <summary> 46 /// 壓縮zip 47 /// </summary> 48 /// <param name="fileToZips">文件路徑集合</param> 49 /// <param name="zipedFile">想要壓成zip的文件名</param> 50 /// <param name="fileDirStart">文件夾起始目錄結尾必須反斜杠</param> 51 public static void Zip(string[] fileToZips, string zipedFile,string fileDirStart) 52 { 53 using (ZipFile zip = new ZipFile(zipedFile, Encoding.UTF8)) 54 { 55 foreach (string fileToZip in fileToZips) 56 { 57 string fileName = fileToZip.Substring(fileToZip.LastIndexOf("\\", StringComparison.Ordinal) + 1); 58 zip.AddFile(fileToZip, fileToZip.Replace(fileDirStart, "").Replace(fileName, "")); 59 //zip.AddFile(fileToZip, fileToZip.Replace(fileDirStart, "").Replace(fileName, "")); 60 //using (var fs = new FileStream(fileToZip, FileMode.Open, FileAccess.ReadWrite)) 61 //{ 62 // var buffer = new byte[fs.Length]; 63 // fs.Read(buffer, 0, buffer.Length); 64 // string fileName = fileToZip.Substring(fileToZip.LastIndexOf("\\", StringComparison.Ordinal) + 1); 65 // zip.AddEntry(fileName, buffer); 66 //} 67 } 68 zip.Save(); 69 } 70 } 71 72 public static void ZipOneFile(string from, string zipedFile, string to) 73 { 74 using (ZipFile zip = new ZipFile(zipedFile, Encoding.UTF8)) 75 { 76 zip.AddFile(from, to); 77 zip.Save(); 78 } 79 } 80 81 }
使用方法:
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,這個問題顯而易見,服務器如果沒有安裝,或者不給權限同樣無法使用,我就遇到了,不過給個操作方法代碼
1 public class WinRarHelper 2 { 3 public WinRarHelper() 4 { 5 6 } 7 8 static WinRarHelper() 9 { 10 //判斷是否安裝了WinRar.exe 11 RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\WinRAR.exe"); 12 _existSetupWinRar = !string.IsNullOrEmpty(key.GetValue(string.Empty).ToString()); 13 14 //獲取WinRar.exe路徑 15 _winRarPath = key.GetValue(string.Empty).ToString(); 16 } 17 18 static bool _existSetupWinRar; 19 /// <summary> 20 /// 獲取是否安裝了WinRar的標識 21 /// </summary> 22 public static bool ExistSetupWinRar 23 { 24 get { return _existSetupWinRar; } 25 } 26 27 static string _winRarPath; 28 /// <summary> 29 /// 獲取WinRar.exe路徑 30 /// </summary> 31 public static string WinRarPath 32 { 33 get { return _winRarPath; } 34 } 35 36 #region 壓縮到.rar,這個方法針對目錄壓縮 37 /// <summary> 38 /// 壓縮到.rar,這個方法針對目錄壓縮 39 /// </summary> 40 /// <param name="intputPath">輸入目錄</param> 41 /// <param name="outputPath">輸出目錄</param> 42 /// <param name="outputFileName">輸出文件名</param> 43 public static void CompressRar(string intputPath, string outputPath, string outputFileName) 44 { 45 //rar 執行時的命令、參數 46 string rarCmd; 47 //啟動進程的參數 48 ProcessStartInfo processStartInfo = new ProcessStartInfo(); 49 //進程對象 50 Process process = new Process(); 51 try 52 { 53 if (!ExistSetupWinRar) 54 { 55 throw new ArgumentException("請確認服務器上已安裝WinRar應用!"); 56 } 57 //判斷輸入目錄是否存在 58 if (!Directory.Exists(intputPath)) 59 { 60 throw new ArgumentException("指定的要壓縮目錄不存在!"); 61 } 62 //命令參數 uxinxin修正參數壓縮文件到當前目錄,而不是從盤符開始 63 rarCmd = " a " + outputFileName + " " + "./" + " -r"; 64 //rarCmd = " a " + outputFileName + " " + outputPath + " -r"; 65 //創建啟動進程的參數 66 //指定啟動文件名 67 processStartInfo.FileName = WinRarPath; 68 //指定啟動該文件時的命令、參數 69 processStartInfo.Arguments = rarCmd; 70 //指定啟動窗口模式:隱藏 71 processStartInfo.WindowStyle = ProcessWindowStyle.Hidden; 72 //指定壓縮后到達路徑 73 processStartInfo.WorkingDirectory = outputPath; 74 //創建進程對象 75 76 //指定進程對象啟動信息對象 77 process.StartInfo = processStartInfo; 78 //啟動進程 79 process.Start(); 80 //指定進程自行退行為止 81 process.WaitForExit(); 82 //Uxinxin增加的清理關閉,不知道是否有效 83 process.Close(); 84 process.Dispose(); 85 } 86 catch (Exception ex) 87 { 88 throw ex; 89 } 90 finally 91 { 92 process.Close(); 93 process.Dispose(); 94 95 } 96 } 97 #endregion 98 99 #region 解壓.rar 100 /// <summary> 101 /// 解壓.rar 102 /// </summary> 103 /// <param name="inputRarFileName">輸入.rar</param> 104 /// <param name="outputPath">輸出目錄</param> 105 public static void UnCompressRar(string inputRarFileName, string outputPath) 106 { 107 //rar 執行時的命令、參數 108 string rarCmd; 109 //啟動進程的參數 110 ProcessStartInfo processStartInfo = new ProcessStartInfo(); 111 //進程對象 112 Process process = new Process(); 113 try 114 { 115 if (!ExistSetupWinRar) 116 { 117 throw new ArgumentException("請確認服務器上已安裝WinRar應用!"); 118 } 119 //如果壓縮到目標路徑不存在 120 if (!Directory.Exists(outputPath)) 121 { 122 //創建壓縮到目標路徑 123 Directory.CreateDirectory(outputPath); 124 } 125 rarCmd = "x " + inputRarFileName + " " + outputPath + " -y"; 126 127 128 processStartInfo.FileName = WinRarPath; 129 processStartInfo.Arguments = rarCmd; 130 processStartInfo.WindowStyle = ProcessWindowStyle.Hidden; 131 processStartInfo.WorkingDirectory = outputPath; 132 133 134 process.StartInfo = processStartInfo; 135 process.Start(); 136 process.WaitForExit(); 137 process.Close(); 138 process.Dispose(); 139 } 140 catch (Exception ex) 141 { 142 throw ex; 143 } 144 finally 145 { 146 process.Close(); 147 process.Dispose(); 148 } 149 } 150 #endregion 151 152 #region 將傳入的文件列表壓縮到指定的目錄下 153 /// <summary> 154 /// 將傳入的文件列表壓縮到指定的目錄下 155 /// </summary> 156 /// <param name="sourceFilesPaths">要壓縮的文件路徑列表</param> 157 /// <param name="compressFileSavePath">壓縮文件存放路徑</param> 158 /// <param name="compressFileName">壓縮文件名(全名)</param> 159 public static void CompressFilesToRar(List<string> sourceFilesPaths, string compressFileSavePath, string compressFileName) 160 { 161 //rar 執行時的命令、參數 162 string rarCmd; 163 //啟動進程的參數 164 ProcessStartInfo processStartInfo = new ProcessStartInfo(); 165 //創建進程對象 166 //進程對象 167 Process process = new Process(); 168 try 169 { 170 if (!ExistSetupWinRar) 171 { 172 throw new ArgumentException("Not setuping the winRar, you can Compress.make sure setuped winRar."); 173 } 174 //判斷輸入文件列表是否為空 175 if (sourceFilesPaths == null || sourceFilesPaths.Count < 1) 176 { 177 throw new ArgumentException("CompressRar'arge : sourceFilesPaths cannot be null."); 178 } 179 rarCmd = " a -ep1 -ap " + compressFileName; 180 //-ep1 -ap表示壓縮時不保留原有文件的路徑,都壓縮到壓縮包中即可,調用winrar命令內容可以參考我轉載的另一篇文章:教你如何在DOS(cmd)下使用WinRAR壓縮文件 181 foreach (object filePath in sourceFilesPaths) 182 { 183 rarCmd += " " + filePath.ToString(); //每個文件路徑要與其他的文件用空格隔開 184 } 185 //rarCmd += " -r"; 186 //創建啟動進程的參數 187 188 //指定啟動文件名 189 processStartInfo.FileName = WinRarPath; 190 //指定啟動該文件時的命令、參數 191 processStartInfo.Arguments = rarCmd; 192 //指定啟動窗口模式:隱藏 193 processStartInfo.WindowStyle = ProcessWindowStyle.Hidden; 194 //指定壓縮后到達路徑 195 processStartInfo.WorkingDirectory = compressFileSavePath; 196 197 //指定進程對象啟動信息對象 198 process.StartInfo = processStartInfo; 199 //啟動進程 200 process.Start(); 201 //指定進程自行退行為止 202 process.WaitForExit(); 203 process.Close(); 204 process.Dispose(); 205 } 206 catch (Exception ex) 207 { 208 throw ex; 209 } 210 finally 211 { 212 process.Close(); 213 process.Dispose(); 214 } 215 } 216 #endregion 217 }
調用方法:
if (WinRarHelper.ExistSetupWinRar)
{
try
{
WinRarHelper.CompressRar(Server.MapPath("/"), Server.MapPath("/"), "1.zip");
Response.Write("壓縮完成!" + DateTime.Now);
}
catch (Win32Exception e1)
{
Response.Write(e1.Message + "<br>" + "服務器端禁止是我們網站使用WinRar應用執行!<br>");
}
catch (Exception e1)
{
Response.Write(e1.Message + "<br>" + 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 + "<br>" + "服務器端禁止是我們網站使用WinRar應用執行!<br>");
}
catch (Exception e1)
{
Response.Write(e1.Message);
}
}
最后我找到了一個解壓的時候不用重命名方法的,還好服務器對解壓沒限制
ICSharpCode.SharpZipLib.dll 用到這個文件
參考來自http://www.cnblogs.com/yuangang/p/5581391.html
具體我也不寫了,就看參考網站吧,我也沒改代碼,不錯,記錄一下,花了我整整一天折騰這玩意兒!