封裝 SharpZipLib `FastZip` 的高階工具類,提供壓縮、解壓、進度回呼、完成事件、密碼保護、空目錄處理、ZIP64、MD5 校驗,開箱即用。
using System;
using System.IO;
using System.Security.Cryptography;
using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Zip;
namespace Helper
{
public static class ZipHelper
{
#region 壓縮
///
/// 快速壓縮資料夾
///
/// 來源資料夾路徑
/// 輸出 .zip 路徑
/// 密碼 (可空)
/// 檔案過濾 (如 "*.cs;*.config")
/// 是否包含空目錄
/// 進度回呼 (檔案名, 進度百分比)
/// 進度觸發間隔秒數
/// 單檔完成回呼
public static void CreateZip(
string sourceDir, string zipPath, string password = null,
string fileFilter = null, bool includeEmptyDirs = true,
Action progress = null, double progressIntervalSeconds = 1,
Action completed = null)
{
var events = new FastZipEvents();
if (progress != null)
{
events.Progress = (sender, e) => progress(e.Name, e.PercentComplete);
events.ProgressInterval = TimeSpan.FromSeconds(progressIntervalSeconds);
}
if (completed != null)
events.CompletedFile = (sender, e) => completed(e.Name);
var fastZip = new FastZip(events)
{
CreateEmptyDirectories = includeEmptyDirs,
Password = password,
UseZip64 = UseZip64.On,
RestoreAttributesOnExtract = true,
RestoreDateTimeOnExtract = true
};
fastZip.CreateZip(zipPath, sourceDir, true, fileFilter);
}
#endregion
#region 解壓縮
///
/// 快速解壓縮
///
public static void ExtractZip(
string zipPath, string destDir, string password = null,
Action progress = null, double progressIntervalSeconds = 1,
Action completed = null)
{
var events = new FastZipEvents();
if (progress != null)
{
events.Progress = (sender, e) => progress(e.Name, e.PercentComplete);
events.ProgressInterval = TimeSpan.FromSeconds(progressIntervalSeconds);
}
if (completed != null)
events.CompletedFile = (sender, e) => completed(e.Name);
var fastZip = new FastZip(events)
{
CreateEmptyDirectories = true,
Password = password,
UseZip64 = UseZip64.On,
RestoreAttributesOnExtract = true,
RestoreDateTimeOnExtract = true
};
fastZip.ExtractZip(zipPath, destDir, FastZip.Overwrite.Always, null, "", "", true);
}
#endregion
#region 工具方法
/// 取得壓縮包內檔案總大小 (位元組)
public static long GetZipSize(string zipPath, string fileFilter = null, string dirFilter = null)
{
long total = 0;
using (var zipFile = new ZipFile(zipPath))
{
var fileFilterObj = new PathFilter(fileFilter ?? "*");
var dirFilterObj = new PathFilter(dirFilter ?? "*");
foreach (ZipEntry entry in zipFile)
{
if (entry.IsFile)
{
string dir = Path.GetDirectoryName(entry.Name);
if (dirFilterObj.IsMatch(dir) && fileFilterObj.IsMatch(Path.GetFileName(entry.Name)))
total += entry.Size;
}
}
}
return total;
}
/// 計算檔案 MD5 (十六進位小寫)
public static string GetMD5(string filePath)
{
using (var fs = File.OpenRead(filePath))
using (var md5 = MD5.Create())
{
byte[] hash = md5.ComputeHash(fs);
return BitConverter.ToString(hash).Replace("-", "").ToLower();
}
}
/// 解壓縮指定單一檔案
public static void ExtractSingleFile(string zipPath, string fileNameInZip, string destDir, string password = null)
{
using (var zipFile = new ZipFile(zipPath))
{
if (!string.IsNullOrEmpty(password))
zipFile.Password = password;
ZipEntry entry = zipFile[fileNameInZip];
if (entry != null && entry.IsFile)
{
string destPath = Path.Combine(destDir, entry.Name);
Directory.CreateDirectory(Path.GetDirectoryName(destPath));
using (var input = zipFile.GetInputStream(entry))
using (var output = File.Create(destPath))
input.CopyTo(output);
}
}
}
#endregion
}
}
// 1. 壓縮資料夾,含進度顯示
ZipHelper.CreateZip(
@"D:\Projects\MyApp", @"D:\Backups\MyApp.zip",
password: "secret123",
fileFilter: "*.cs;*.json;*.config",
includeEmptyDirs: true,
progress: (name, pct) => Console.WriteLine($"[{pct:F1}%] {name}"),
completed: name => Console.WriteLine($"完成: {name}")
);
// 2. 解壓縮
ZipHelper.ExtractZip(
@"D:\Backups\MyApp.zip", @"D:\Restore\MyApp",
password: "secret123",
progress: (name, pct) => Console.WriteLine($"解壓 [{pct:F1}%] {name}")
);
// 3. 取得壓縮包大小
long size = ZipHelper.GetZipSize(@"D:\Backups\MyApp.zip");
Console.WriteLine($"總大小: {size:N0} bytes");
// 4. 驗證檔案完整性
string md5 = ZipHelper.GetMD5(@"D:\Backups\MyApp.zip");
Console.WriteLine($"MD5: {md5}");
// 5. 僅解壓單一檔案
ZipHelper.ExtractSingleFile(@"D:\Backups\MyApp.zip", "appsettings.json", @"D:\Temp");
| 參數 | 用途 |
|---|---|
| UseZip64.On | 支援 >4GB 壓縮包、>65535 個檔案 |
| RestoreAttributesOnExtract | 還原檔案屬性 (唯讀、隱藏等) |
| RestoreDateTimeOnExtract | 還原建立/修改時間 |
| FastZip.Overwrite.Always | 解壓時無條件覆蓋同名檔案 |
| PathFilter | 支援 `*` `?` 通配符的路徑/檔名過濾 |
Install-Package SharpZipLib
// 或
dotnet add package SharpZipLib
SharpZipLib 是 .NET 生態最成熟的純管理代碼壓縮庫,無原生相依、跨平台、支援 .NET Framework/.NET Core/.NET 5+。生產環境大檔案建議改用 `ZipFile` 串流式處理避免記憶體壓力。