平安校园
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

534 lines
17 KiB

  1. //
  2. namespace SafeCampus.Core.Utils;
  3. public class ZipUtils
  4. {
  5. /// <summary>
  6. /// 压缩单个文件
  7. /// </summary>
  8. /// <param name="fileToZip">要压缩的文件</param>
  9. /// <param name="zipedFile">压缩后的文件</param>
  10. /// <param name="compressionLevel">压缩等级</param>
  11. /// <param name="blockSize">每次写入大小</param>
  12. public static void ZipFile(string fileToZip, string zipedFile, int compressionLevel,
  13. int blockSize)
  14. {
  15. //如果文件没有找到,则报错
  16. if (!File.Exists(fileToZip))
  17. {
  18. throw new FileNotFoundException("指定要压缩的文件: " + fileToZip + " 不存在!");
  19. }
  20. using (var zipFile = File.Create(zipedFile))
  21. {
  22. using (var zipStream = new ZipOutputStream(zipFile))
  23. {
  24. using (var streamToZip = new FileStream(fileToZip, FileMode.Open, FileAccess.Read))
  25. {
  26. var fileName = fileToZip.Substring(fileToZip.LastIndexOf("\\", StringComparison.Ordinal) + 1);
  27. var zipEntry = new ZipEntry(fileName);
  28. zipStream.PutNextEntry(zipEntry);
  29. zipStream.SetLevel(compressionLevel);
  30. var buffer = new byte[blockSize];
  31. try
  32. {
  33. var sizeRead = 0;
  34. do
  35. {
  36. sizeRead = streamToZip.Read(buffer, 0, buffer.Length);
  37. zipStream.Write(buffer, 0, sizeRead);
  38. } while (sizeRead > 0);
  39. }
  40. catch (Exception ex)
  41. {
  42. throw ex;
  43. }
  44. streamToZip.Close();
  45. }
  46. zipStream.Finish();
  47. zipStream.Close();
  48. }
  49. zipFile.Close();
  50. }
  51. }
  52. /// <summary>
  53. /// 压缩单个文件
  54. /// </summary>
  55. /// <param name="fileToZip">要进行压缩的文件名</param>
  56. /// <param name="zipedFile">压缩后生成的压缩文件名</param>
  57. public static void ZipFile(string fileToZip, string zipedFile)
  58. {
  59. //如果文件没有找到,则报错
  60. if (!File.Exists(fileToZip))
  61. {
  62. throw new FileNotFoundException("指定要压缩的文件: " + fileToZip + " 不存在!");
  63. }
  64. using (var fs = File.OpenRead(fileToZip))
  65. {
  66. var buffer = new byte[fs.Length];
  67. fs.Read(buffer, 0, buffer.Length);
  68. fs.Close();
  69. using (var zipFile = File.Create(zipedFile))
  70. {
  71. using (var zipStream = new ZipOutputStream(zipFile))
  72. {
  73. var fileName = fileToZip.Substring(fileToZip.LastIndexOf("\\") + 1);
  74. var zipEntry = new ZipEntry(fileName);
  75. zipStream.PutNextEntry(zipEntry);
  76. zipStream.SetLevel(5);
  77. zipStream.Write(buffer, 0, buffer.Length);
  78. zipStream.Finish();
  79. zipStream.Close();
  80. }
  81. }
  82. }
  83. }
  84. /// <summary>
  85. /// 压缩多个文件到指定路径
  86. /// </summary>
  87. /// <param name="sourceFileNames">压缩到哪个路径</param>
  88. /// <param name="zipFileName">压缩文件名称</param>
  89. public static void ZipFile(List<string> sourceFileNames, string zipFileName)
  90. {
  91. //压缩文件打包
  92. using (var s = new ZipOutputStream(File.Create(zipFileName)))
  93. {
  94. s.SetLevel(9);
  95. var buffer = new byte[4096];
  96. foreach (var file in sourceFileNames)
  97. {
  98. if (Directory.Exists(file))// 先当作目录处理如果存在这个目录就递归Copy该目录下面的文件
  99. {
  100. var pPath = "";
  101. pPath += Path.GetFileName(file);
  102. pPath += "\\";
  103. ZipSetp(file, s, pPath, sourceFileNames);
  104. }
  105. else// 否则直接压缩文件
  106. {
  107. var entry = new ZipEntry(Path.GetFileName(file));
  108. entry.DateTime = DateTime.Now;
  109. s.PutNextEntry(entry);
  110. using (var fs = File.OpenRead(file))
  111. {
  112. int sourceBytes;
  113. do
  114. {
  115. sourceBytes = fs.Read(buffer, 0, buffer.Length);
  116. s.Write(buffer, 0, sourceBytes);
  117. } while (sourceBytes > 0);
  118. }
  119. }
  120. }
  121. s.Finish();
  122. s.Close();
  123. }
  124. }
  125. /// <summary>
  126. /// 压缩多层目录
  127. /// </summary>
  128. /// <param name="strDirectory">待压缩目录</param>
  129. /// <param name="zipedFile">压缩后生成的压缩文件名,绝对路径</param>
  130. public static void ZipFileDirectory(string strDirectory, string zipedFile)
  131. {
  132. using (var zipFile = File.Create(zipedFile))
  133. {
  134. using (var s = new ZipOutputStream(zipFile))
  135. {
  136. s.SetLevel(9);
  137. ZipSetp(strDirectory, s, "");
  138. }
  139. }
  140. }
  141. /// <summary>
  142. /// 压缩多层目录
  143. /// </summary>
  144. /// <param name="strDirectory">待压缩目录</param>
  145. /// <param name="zipedFile">压缩后生成的压缩文件名,绝对路径</param>
  146. /// <param name="files">指定要压缩的文件列表(完全路径)</param>
  147. public static void ZipFileDirectory(string strDirectory, string zipedFile, List<string> files)
  148. {
  149. using (var zipFile = File.Create(zipedFile))
  150. {
  151. using (var s = new ZipOutputStream(zipFile))
  152. {
  153. s.SetLevel(9);
  154. ZipSetp(strDirectory, s, "", files);
  155. }
  156. }
  157. }
  158. /// <summary>
  159. /// 递归遍历目录
  160. /// </summary>
  161. /// <param name="strDirectory">需遍历的目录</param>
  162. /// <param name="s">压缩输出流对象</param>
  163. /// <param name="parentPath">The parent path.</param>
  164. /// <param name="files">需要压缩的文件</param>
  165. private static void ZipSetp(string strDirectory, ZipOutputStream s, string parentPath,
  166. List<string> files = null)
  167. {
  168. if (strDirectory[strDirectory.Length - 1] != Path.DirectorySeparatorChar)
  169. {
  170. strDirectory += Path.DirectorySeparatorChar;
  171. }
  172. var filenames = Directory.GetFileSystemEntries(strDirectory);
  173. var buffer = new byte[4096];
  174. foreach (var file in filenames)// 遍历所有的文件和目录
  175. {
  176. if (files != null && !files.Contains(file))
  177. {
  178. continue;
  179. }
  180. if (Directory.Exists(file))// 先当作目录处理如果存在这个目录就递归Copy该目录下面的文件
  181. {
  182. var pPath = parentPath;
  183. pPath += Path.GetFileName(file);
  184. pPath += "\\";
  185. ZipSetp(file, s, pPath, files);
  186. }
  187. else// 否则直接压缩文件
  188. {
  189. //打开压缩文件
  190. var fileName = parentPath + Path.GetFileName(file);
  191. var entry = new ZipEntry(fileName);
  192. entry.DateTime = DateTime.Now;
  193. s.PutNextEntry(entry);
  194. using (var fs = File.OpenRead(file))
  195. {
  196. int sourceBytes;
  197. do
  198. {
  199. sourceBytes = fs.Read(buffer, 0, buffer.Length);
  200. s.Write(buffer, 0, sourceBytes);
  201. } while (sourceBytes > 0);
  202. }
  203. }
  204. }
  205. }
  206. /// <summary>
  207. /// 解压缩一个 zip 文件。
  208. /// </summary>
  209. /// <param name="zipedFile">压缩文件</param>
  210. /// <param name="strDirectory">解压目录</param>
  211. /// <param name="password">zip 文件的密码。</param>
  212. /// <param name="overWrite">是否覆盖已存在的文件。</param>
  213. public static void UnZip(string zipedFile, string strDirectory, bool overWrite,
  214. string password)
  215. {
  216. if (strDirectory == "")
  217. strDirectory = Directory.GetCurrentDirectory();
  218. if (!strDirectory.EndsWith("\\"))
  219. strDirectory = strDirectory + "\\";
  220. using (var s = new ZipInputStream(File.OpenRead(zipedFile)))
  221. {
  222. if (password != null)
  223. {
  224. s.Password = password;
  225. }
  226. ZipEntry theEntry;
  227. while ((theEntry = s.GetNextEntry()) != null)
  228. {
  229. var directoryName = "";
  230. var pathToZip = "";
  231. pathToZip = theEntry.Name;
  232. if (pathToZip != "")
  233. directoryName = Path.GetDirectoryName(pathToZip) + "\\";
  234. var fileName = Path.GetFileName(pathToZip);
  235. Directory.CreateDirectory(strDirectory + directoryName);
  236. if (fileName != "")
  237. {
  238. if (File.Exists(strDirectory + directoryName + fileName) && overWrite || !File.Exists(strDirectory + directoryName + fileName))
  239. {
  240. using (var streamWriter = File.Create(strDirectory + directoryName + fileName))
  241. {
  242. var size = 2048;
  243. var data = new byte[2048];
  244. while (true)
  245. {
  246. size = s.Read(data, 0, data.Length);
  247. if (size > 0)
  248. streamWriter.Write(data, 0, size);
  249. else
  250. break;
  251. }
  252. streamWriter.Close();
  253. }
  254. }
  255. }
  256. }
  257. s.Close();
  258. }
  259. }
  260. /// <summary>
  261. /// 解压缩一个 zip 文件。
  262. /// </summary>
  263. /// <param name="zipedFile">压缩文件</param>
  264. /// <param name="strDirectory">解压目录</param>
  265. /// <param name="overWrite">是否覆盖已存在的文件。</param>
  266. public static void UnZip(string zipedFile, string strDirectory, bool overWrite)
  267. {
  268. UnZip(zipedFile, strDirectory, overWrite, null);
  269. }
  270. /// <summary>
  271. /// 解压缩一个 zip 文件。
  272. /// 覆盖已存在的文件。
  273. /// </summary>
  274. /// <param name="zipedFile">压缩文件</param>
  275. /// <param name="strDirectory">解压目录</param>
  276. public static void UnZip(string zipedFile, string strDirectory)
  277. {
  278. UnZip(zipedFile, strDirectory, true);
  279. }
  280. /// <summary>
  281. /// 获取压缩文件中指定类型的文件
  282. /// </summary>
  283. /// <param name="zipedFile">压缩文件</param>
  284. /// <param name="fileExtension">文件类型(.txt|.exe)</param>
  285. /// <returns>文件名称列表(包含子目录)</returns>
  286. public static List<string> GetFiles(string zipedFile, List<string> fileExtension)
  287. {
  288. var files = new List<string>();
  289. if (!File.Exists(zipedFile))
  290. {
  291. //return files;
  292. throw new FileNotFoundException(zipedFile);
  293. }
  294. using (var s = new ZipInputStream(File.OpenRead(zipedFile)))
  295. {
  296. ZipEntry theEntry;
  297. while ((theEntry = s.GetNextEntry()) != null)
  298. {
  299. if (theEntry.IsFile)
  300. {
  301. //Console.WriteLine("Name : {0}", theEntry.Name);
  302. if (fileExtension != null)
  303. {
  304. if (fileExtension.Contains(Path.GetExtension(theEntry.Name)))
  305. {
  306. files.Add(theEntry.Name);
  307. }
  308. }
  309. else
  310. {
  311. files.Add(theEntry.Name);
  312. }
  313. }
  314. }
  315. s.Close();
  316. }
  317. return files;
  318. }
  319. /// <summary>
  320. /// 获取压缩文件中的所有文件
  321. /// </summary>
  322. /// <param name="zipedFile">压缩文件</param>
  323. /// <returns>文件名称列表(包含子目录)</returns>
  324. public static List<string> GetFiles(string zipedFile)
  325. {
  326. return GetFiles(zipedFile, null);
  327. }
  328. /// <summary>
  329. /// 打包线上线下文件
  330. /// </summary>
  331. /// <param name="zipName">压缩文件名称</param>
  332. /// <param name="fileList">文件列表</param>
  333. /// <param name="error">保存路径</param>
  334. /// <param name="isLocal">是否本地</param>
  335. public static string ZipFiles(string zipName, List<FileItem> fileList, out string error,
  336. bool isLocal = true)
  337. {
  338. error = string.Empty;
  339. var path = string.Format("/ZipFiles/{0}/{1}/{2}/", DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
  340. //文件保存目录
  341. var directory = App.WebHostEnvironment.WebRootPath + path;
  342. var url = App.Configuration["FileHostUrl"].TrimEnd('/') + path + zipName;
  343. var savePath = directory + zipName;
  344. try
  345. {
  346. if (!Directory.Exists(directory))
  347. {
  348. Directory.CreateDirectory(directory);
  349. }
  350. using (var zipStream = new ZipOutputStream(File.Create(savePath)))
  351. {
  352. zipStream.SetLevel(9);//压缩级别0-9
  353. foreach (var item in fileList)
  354. {
  355. byte[] buffer = null;
  356. if (isLocal)
  357. {
  358. var stream = new FileInfo(item.FilePath).OpenRead();
  359. buffer = new byte[stream.Length];
  360. stream.Read(buffer, 0, Convert.ToInt32(stream.Length));
  361. }
  362. else
  363. {
  364. buffer = new WebClient().DownloadData(item.FilePath);//取消
  365. }
  366. var entry = new ZipEntry(item.FileName);
  367. entry.DateTime = DateTime.Now;
  368. entry.Size = buffer.Length;
  369. zipStream.PutNextEntry(entry);
  370. zipStream.Write(buffer, 0, buffer.Length);
  371. }
  372. }
  373. }
  374. catch (Exception ex)
  375. {
  376. error = "文件打包失败:" + ex.Message;
  377. }
  378. return url;
  379. }
  380. /// 压缩文件夹
  381. /// 要打包的文件夹
  382. /// 是否删除原文件夹
  383. public static string CompressDirectory(string dirPath, bool deleteDir)
  384. {
  385. //压缩文件路径
  386. var pCompressPath = dirPath + ".zip";
  387. if (File.Exists(pCompressPath))
  388. File.Delete(pCompressPath);
  389. //创建压缩文件
  390. var pCompressFile = new FileStream(pCompressPath, FileMode.Create);
  391. using (var zipoutputstream = new ZipOutputStream(pCompressFile))
  392. {
  393. var crc = new Crc32();
  394. var fileList = GetAllFies(dirPath);
  395. foreach (var item in fileList)
  396. {
  397. var fs = new FileStream(item.Key, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
  398. // FileStream fs = File.OpenRead(item.Key.ToString());
  399. var buffer = new byte[fs.Length];
  400. fs.Read(buffer, 0, buffer.Length);
  401. var entry = new ZipEntry(item.Key.Substring(dirPath.Length));
  402. entry.DateTime = item.Value;
  403. entry.Size = fs.Length;
  404. fs.Close();
  405. crc.Reset();
  406. crc.Update(buffer);
  407. entry.Crc = crc.Value;
  408. zipoutputstream.PutNextEntry(entry);
  409. zipoutputstream.Write(buffer, 0, buffer.Length);
  410. }
  411. }
  412. if (deleteDir)
  413. {
  414. Directory.Delete(dirPath, true);
  415. }
  416. return pCompressPath;
  417. }
  418. ///
  419. /// 获取所有文件
  420. ///
  421. ///
  422. private static Dictionary<string, DateTime> GetAllFies(string dir)
  423. {
  424. var filesList = new Dictionary<string, DateTime>();
  425. var fileDire = new DirectoryInfo(dir);
  426. if (!fileDire.Exists)
  427. {
  428. throw new FileNotFoundException("目录:" + fileDire.FullName + "没有找到!");
  429. }
  430. GetAllDirFiles(fileDire, filesList);
  431. GetAllDirsFiles(fileDire.GetDirectories(), filesList);
  432. return filesList;
  433. }
  434. ///
  435. /// 获取一个文件夹下的所有文件夹里的文件
  436. ///
  437. ///
  438. ///
  439. private static void GetAllDirsFiles(DirectoryInfo[] dirs, Dictionary<string, DateTime> filesList)
  440. {
  441. foreach (var dir in dirs)
  442. {
  443. foreach (var file in dir.GetFiles("."))
  444. {
  445. filesList.Add(file.FullName, file.LastWriteTime);
  446. }
  447. GetAllDirsFiles(dir.GetDirectories(), filesList);
  448. }
  449. }
  450. ///
  451. /// 获取一个文件夹下的文件
  452. ///
  453. /// 目录名称
  454. /// 文件列表HastTable
  455. private static void GetAllDirFiles(DirectoryInfo dir, Dictionary<string, DateTime> filesList)
  456. {
  457. foreach (var file in dir.GetFiles())
  458. {
  459. filesList.Add(file.FullName, file.LastWriteTime);
  460. }
  461. }
  462. }
  463. /// <summary>
  464. /// 文件对象
  465. /// </summary>
  466. public class FileItem
  467. {
  468. /// <summary>
  469. /// 文件名称
  470. /// </summary>
  471. public string FileName { get; set; }
  472. /// <summary>
  473. /// 文件路径
  474. /// </summary>
  475. public string FilePath { get; set; }
  476. }