接口
public interface IUnZip
{
/// <summary>
/// 功能:解壓zip格式的文件。
/// </summary>
/// <param name="zipFilePath">壓縮文件路徑</param>
/// <param name="unZipDir">解壓文件存放路徑,爲空時默認與壓縮文件同一級目錄下,跟壓縮文件同名的文件夾</param>
/// <param name="password">壓縮包密碼</param>
/// <returns>解壓後文件所在的文件夾</returns>
string UnZipFile(string zipFilePath, string unZipDir = null, string password = null);
}
public interface IZip
{
/// <summary>
/// 將選定的文件壓入一個目標zip中
/// </summary>
/// <param name="list">選定的文件/文件夾(路徑的集合)</param>
/// <param name="targetFileName">壓縮後獲得的zip保存路徑</param>
/// <param name="password">壓縮包密碼</param>
/// <param name="overwrite">若是Zip文件已存在,是否覆蓋</param>
/// <param name="level">壓縮等級0—9</param>
/// <returns>壓縮包路徑</returns>
void Compress(List<string> list, string targetFileName, string password = null, bool overwrite = true, int level = 9);
/// <summary>
/// 將選定的文件壓入一個目標zip中
/// </summary>
/// <param name="fileOrDir">選定的文件/文件夾</param>
/// <param name="targetFileName">壓縮後獲得的zip保存路徑</param>
/// <param name="password">壓縮包密碼</param>
/// <param name="overwrite">若是Zip文件已存在,是否覆蓋</param>
/// <param name="level">壓縮等級0—9</param>
/// <returns>壓縮包路徑</returns>
void Compress(string fileOrDir, string targetFileName, string password = null, bool overwrite = true, int level = 9);
}
public interface IZipHelper:IZip,IUnZip
{
}
實現
public class ZipHelper : IZipHelper
{
#region 壓縮文件
/// <inheritdoc/>
public void Compress(string fileOrDir, string targetFileName, string password = null, bool overwrite = true, int level = 9)
{
List<string> list = new List<string> { fileOrDir };
Compress(list, targetFileName, password, overwrite,level);
}
/// <inheritdoc/>
public void Compress(List<string> list, string targetFileName, string password = null, bool overwrite = true,int level = 9)
{
CheckForCompress(list, targetFileName, overwrite);
//若是已經存在目標文件,刪除
if (File.Exists(targetFileName))
{
File.Delete(targetFileName);
}
ZipOutputStream zips = null;
FileStream fileStream = null;
try
{
fileStream = File.Create(targetFileName);
zips = new ZipOutputStream(fileStream);
zips.SetLevel(level % 10); //壓縮等級
zips.Password = password;
foreach (string dir in list)
{
if (File.Exists(dir))
{
AddFile("",dir, zips);
}
else
{
CompressFolder("", dir, zips);
}
}
zips.Finish();
}
catch { throw; }
finally
{
if(fileStream!= null)
{
fileStream.Close();
fileStream.Dispose();
}
if(zips!= null)
{
zips.Close();
zips.Dispose();
}
}
}
#region private
private void CheckForCompress(List<string> files, string targetFileName, bool overwrite)
{
//由於files可能來自不一樣的文件夾,因此不方便自動提供一個默認文件夾,須要提供
if (!overwrite && File.Exists(targetFileName))
{
throw new Exception("目標zip文件已存在!");
}
//待壓入的文件或文件夾須要真實存在
foreach (var item in files)
{
if (!File.Exists(item) && !Directory.Exists(item))
{
throw new Exception($"文件/文件夾【{item}】不存在!");
}
}
//不能有同名的文件/文件夾
Dictionary<string, string> dic = new Dictionary<string, string>();
foreach (var item in files)
{
string item_ = item.TrimEnd('/', '\\');
string fileName = Path.GetFileName(item_);
if (dic.ContainsKey(fileName))
{
throw new Exception($"選中的文件/文件夾中存在同名衝突:【{dic[fileName]}】,【{item_}】");
}
else
{
dic[fileName] = item_;
}
}
}
private void AddFile(string orignalDir, string file, ZipOutputStream zips)
{
//文件
FileStream StreamToZip = null;
try
{
//加入ZIP文件條目(爲壓縮文件流提供一個容器)
StreamToZip = new FileStream(file, FileMode.Open, FileAccess.Read);
string fileName = Path.GetFileName(file);
if (!string.IsNullOrEmpty(orignalDir))
{
fileName = orignalDir + Path.DirectorySeparatorChar + fileName;
}
ZipEntry z = new ZipEntry(fileName);
zips.PutNextEntry(z);
//寫入文件流
int pack = 10240; //10Kb
byte[] buffer = new byte[pack];
int size = StreamToZip.Read(buffer, 0, buffer.Length);
while (size > 0)
{
zips.Write(buffer, 0, size);
size = StreamToZip.Read(buffer, 0, buffer.Length);
}
}
catch { throw; }
finally
{
if (StreamToZip != null)
{
StreamToZip.Close();
StreamToZip.Dispose();
}
}
}
private void AddFolder(string orignalDir, string folder, ZipOutputStream zips)
{
//文件夾
folder = folder.TrimEnd('/','\\');
string fileName = Path.GetFileName(folder);
if (!string.IsNullOrEmpty(orignalDir))
{
fileName = orignalDir + Path.DirectorySeparatorChar + fileName ;
}
fileName += Path.DirectorySeparatorChar;
ZipEntry z = new ZipEntry(fileName);
zips.PutNextEntry(z);
}
/// <summary>
/// 遞歸壓縮文件夾內全部文件和子文件夾
/// </summary>
/// <param name="orignalDir">外層文件夾</param>
/// <param name="dir">被壓縮文件夾</param>
/// <param name="zips">流</param>
private void CompressFolder(string orignalDir,string dir, ZipOutputStream zips)
{
// 壓縮當前文件夾下全部文件
string[] names = Directory.GetFiles(dir);
foreach (string fileName in names)
{
AddFile(orignalDir,fileName, zips);
}
// 壓縮子文件夾
names = Directory.GetDirectories(dir);
foreach (string folderName in names)
{
AddFolder(orignalDir, folderName, zips);
string _orignalDir = Path.GetFileName(folderName);
if (!string.IsNullOrEmpty(orignalDir))
{
_orignalDir = orignalDir + Path.DirectorySeparatorChar + _orignalDir;
}
CompressFolder(_orignalDir, folderName, zips);
}
}
#endregion private
#endregion 壓縮文件
#region 解壓文件
/// <inheritdoc/>
public string UnZipFile(string zipFilePath, string unZipDir = null,string password = null)
{
if (!File.Exists(zipFilePath))
{
throw new Exception($"壓縮文件【{zipFilePath}】不存在!");
}
//解壓文件夾爲空時默認與壓縮文件同一級目錄下,跟壓縮文件同名的文件夾
if (string.IsNullOrWhiteSpace(unZipDir))
{
unZipDir = Path.GetDirectoryName(zipFilePath);
string name = Path.GetFileNameWithoutExtension(zipFilePath);
unZipDir = Path.Combine(unZipDir, name);
}
string unZipDir2 = unZipDir;
char lastChar = unZipDir[unZipDir.Length - 1];
if (lastChar != '/' && lastChar != '\\')
{
unZipDir += Path.DirectorySeparatorChar;
}
if (!Directory.Exists(unZipDir))
Directory.CreateDirectory(unZipDir);
//解壓
UnZipProcess(zipFilePath, unZipDir, password);
return unZipDir2;
}
private void UnZipProcess(string zipFilePath, string unZipDir, string password)
{
ZipInputStream zipInput = null;
FileStream fileStream = null;
try
{
fileStream = File.OpenRead(zipFilePath);
zipInput = new ZipInputStream(fileStream);
zipInput.Password = password;
ZipEntry theEntry;
while ((theEntry = zipInput.GetNextEntry()) != null)
{
string tempPath = unZipDir + theEntry.Name;
if (theEntry.IsDirectory)
{
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(tempPath);
}
}
else
{
using (FileStream streamWriter = File.Create(tempPath))
{
byte[] buffer = new byte[10240];
int size = zipInput.Read(buffer, 0, buffer.Length);
while (size > 0)
{
streamWriter.Write(buffer, 0, size);
size = zipInput.Read(buffer, 0, buffer.Length);
}
}
}
}
}
catch
{
throw;
}
finally
{
if (fileStream != null)
{
fileStream.Close();
fileStream.Dispose();
}
if (zipInput != null)
{
zipInput.Close();
zipInput.Dispose();
}
}
}
#endregion
}