C#執行zip文件壓縮的幾種方法及我遇到的坑總結


工作項目中需要用到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

具體我也不寫了,就看參考網站吧,我也沒改代碼,不錯,記錄一下,花了我整整一天折騰這玩意兒!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM