您的位置:首页 > 编程语言 > C#

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

2017-01-10 09:36 549 查看
工作项目中需要用到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

具体我也不写了,就看参考网站吧,我也没改代码,不错,记录一下,花了我整整一天折腾这玩意儿!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: