Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add folder, unable to decompress #883

Open
Luohui109 opened this issue Nov 14, 2024 · 1 comment
Open

Add folder, unable to decompress #883

Luohui109 opened this issue Nov 14, 2024 · 1 comment
Labels
bug zip Related to ZIP file format

Comments

@Luohui109
Copy link

Luohui109 commented Nov 14, 2024

Describe the bug

Version SharpZipLib. 1.3.3
I'm not sure that version 4 has this issue
“Stored, but compressed != uncompressed”

Reproduction Code

No response

Steps to reproduce

Step 1:
namespace SoluM.Utils.Zip
{
using ICSharpCode.SharpZipLib.Zip;
using System.Collections;
using System.IO;
using System.Threading;

/// <summary>
/// ICSharpCode.SharpZipLib.Zip
/// </summary>
public class ZipHelper
{
	/// <summary>
    /// 缓存字节数
    /// </summary>
    private const int BufferSize = 1024;

    /// <summary>
    /// 压缩最小等级
    /// </summary>
    public const int CompressionLevelMin = 0;

    /// <summary>
    /// 压缩最大等级
    /// </summary>
    public const int CompressionLevelMax = 9;
	
	internal static int CheckCompressionLevel(int compressionlevel)
    {
        return compressionlevel < CompressionLevelMin ? CompressionLevelMin : compressionlevel > CompressionLevelMax ? CompressionLevelMax : compressionlevel;
    }
	
	public class FileEntry
	{
		/// <summary>
		/// 
		/// </summary>
		public string Name { get; set; }
		/// <summary>
		/// 
		/// </summary>
		public string FullName { get; set; }
		/// <summary>
		/// 
		/// </summary>
		public string ZipEntryName { get; set; }
		/// <summary>
		/// 
		/// </summary>
		public bool IsDirectory { get; set; }
		/// <summary>
		/// 
		/// </summary>
		public string Extension { get; set; }
		/// <summary>
		/// 
		/// </summary>
		public long Length { get; set; }
		/// <summary>
		/// 
		/// </summary>
		public bool ReadOnly { get; set; }
		/// <summary>
		/// 
		/// </summary>
		public FileAttributes Attributes { get; set; }
		/// <summary>
		/// 
		/// </summary>
		public DateTime CreationTime { get; set; }
		/// <summary>
		/// 
		/// </summary>
		public DateTime LastAccessTime { get; set; }
		/// <summary>
		/// 
		/// </summary>
		public DateTime LastWriteTime { get; set; }
	}

public static bool IsDiskOnly(string path)
{
bool result = false;

        if (!string.IsNullOrWhiteSpace(path) && (File.Exists(path) || Directory.Exists(path)))
        {
            DirectoryInfo directoryInfo = new DirectoryInfo(path);

            result = directoryInfo.Root.FullName == directoryInfo.FullName;
        }

        return result;
    }

    public static bool HasDescendants(string path)
    {
        bool result = false;

        if (!string.IsNullOrWhiteSpace(path) && (File.Exists(path) || Directory.Exists(path)))
        {
            if (File.Exists(path))
            {
                result = true;
            }
            else if (Directory.Exists(path))
            {
                result = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories).Length > 0;
            }
        }

        return result;
    }
	public static List<FileEntry> GetFileEntry(string path, bool includedemptydir = true)
	{
		List<FileEntry> fileEntryList = new List<FileEntry>();

		FileEntry fileEntry;
		FileInfo fileInfo;
		DirectoryInfo directoryInfo;

		//校验待添加到压缩包的全路径文件或文件夹
		if (!string.IsNullOrWhiteSpace(path))
		{
			//
			if (path.EndsWith(@"\"))
			{
				path = path.Remove(path.LastIndexOf(@"\"));
			}

			if (File.Exists(path))
			{
				fileInfo = new FileInfo(path);
				fileEntry = new FileEntry();
				fileEntry.Name = fileInfo.Name;
				fileEntry.FullName = fileInfo.FullName;
				fileEntry.ZipEntryName = fileInfo.Name;
				fileEntry.IsDirectory = false;
				fileEntry.Extension = fileInfo.Extension;
				fileEntry.Length = fileInfo.Length;
				fileEntry.ReadOnly = fileInfo.IsReadOnly;
				fileEntry.Attributes = fileInfo.Attributes;
				fileEntry.CreationTime = fileInfo.CreationTime;
				fileEntry.LastAccessTime = fileInfo.LastAccessTime;
				fileEntry.LastWriteTime = fileInfo.LastWriteTime;
				fileEntryList.Add(fileEntry);
			}
			else if (Directory.Exists(path))
			{
				if (!IsDiskOnly(path))
				{
					if (includedemptydir || HasDescendants(path))
					{
						string parentPath = Path.GetDirectoryName(path) + @"\";

						if (parentPath.EndsWith(@":\\"))
						{
							parentPath = parentPath.Replace(@"\\", @"\");
						}

						//先将顶级文件夹压入
						directoryInfo = new DirectoryInfo(path);
						fileEntry = new FileEntry();
						fileEntry.Name = directoryInfo.Name;
						fileEntry.FullName = directoryInfo.FullName;
						fileEntry.ZipEntryName = directoryInfo.FullName.Replace(parentPath, "");
						fileEntry.IsDirectory = true;
						fileEntry.Extension = "";
						fileEntry.Length = 0;
						fileEntry.ReadOnly = default;
						fileEntry.Attributes = directoryInfo.Attributes;
						fileEntry.CreationTime = directoryInfo.CreationTime;
						fileEntry.LastAccessTime = directoryInfo.LastAccessTime;
						fileEntry.LastWriteTime = directoryInfo.LastWriteTime;
						fileEntryList.Add(fileEntry);

						//再将其子孙文件、文件夹压入
						//一次性获取下级所有目录,避免递归
						string[] directories = Directory.GetDirectories(path, "*.*", SearchOption.AllDirectories);
						foreach (string dir in directories)
						{
							if (includedemptydir || HasDescendants(dir))
							{
								directoryInfo = new DirectoryInfo(dir);
								fileEntry = new FileEntry();
								fileEntry.Name = directoryInfo.Name;
								fileEntry.FullName = directoryInfo.FullName;
								fileEntry.ZipEntryName = directoryInfo.FullName.Replace(parentPath, "");
								fileEntry.IsDirectory = true;
								fileEntry.Extension = "";
								fileEntry.Length = 0;
								fileEntry.ReadOnly = default;
								fileEntry.Attributes = directoryInfo.Attributes;
								fileEntry.CreationTime = directoryInfo.CreationTime;
								fileEntry.LastAccessTime = directoryInfo.LastAccessTime;
								fileEntry.LastWriteTime = directoryInfo.LastWriteTime;
								fileEntryList.Add(fileEntry);
							}
						}
						//一次性获取下级所有文件,避免递归
						string[] files = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories);
						foreach (string file in files)
						{
							fileInfo = new FileInfo(file);
							fileEntry = new FileEntry();
							fileEntry.Name = fileInfo.Name;
							fileEntry.FullName = fileInfo.FullName;
							fileEntry.ZipEntryName = fileInfo.FullName.Replace(parentPath, "");
							fileEntry.IsDirectory = false;
							fileEntry.Extension = fileInfo.Extension;
							fileEntry.Length = fileInfo.Length;
							fileEntry.ReadOnly = fileInfo.IsReadOnly;
							fileEntry.Attributes = fileInfo.Attributes;
							fileEntry.CreationTime = fileInfo.CreationTime;
							fileEntry.LastAccessTime = fileInfo.LastAccessTime;
							fileEntry.LastWriteTime = fileInfo.LastWriteTime;
							fileEntryList.Add(fileEntry);
						}
					}
				}
			}
		}

		return fileEntryList;
	}
	public static List<FileEntry> GetFileEntry(IEnumerable<string> pathlist, bool includedemptydir = true)
	{
		List<FileEntry> fileEntryList = new List<FileEntry>();

		foreach (string path in pathlist)
		{
			fileEntryList.AddRange(GetFileEntry(path));
		}

		return fileEntryList;
	}

	public static string Compress(IEnumerable<string> sourcepathlist, string zipfilepath = null, string comment = null, string password = null, int compressionlevel = 6)
	{
		string result = null;

		try
		{
			//
			if (sourcepathlist == null || !(sourcepathlist.Count() > 0))
			{
				throw new Exception("待添加到压缩包的全路径文件或文件夹列表不能为空、NULL或空白字符!");
			}
			//
			foreach (string sourcepath in sourcepathlist)
			{
				if (string.IsNullOrWhiteSpace(sourcepath))
				{
					throw new Exception("待添加到压缩包的全路径文件或文件夹列表中的元素不能为空、NULL或空白字符!");
				}

				if (!(File.Exists(sourcepath) || Directory.Exists(sourcepath)))
				{
					throw new Exception($"待添加到压缩包的全路径文件或文件夹列表中元素[{sourcepath}]在存储设备上不存在!");
				}
			}

			//获取文件、文件夹列表
			List<FileEntry> fileEntryList = GetFileEntry(sourcepathlist);

			//检测目标文件夹是否存在,如果不存在则建立
			string zipFileDirectory = Path.GetDirectoryName(zipfilepath);
			if (!Directory.Exists(zipFileDirectory))
			{
				Directory.CreateDirectory(zipFileDirectory);
			}

			//创建压缩文件,若存在则覆盖
			using (FileStream zipStream = File.Create(zipfilepath))
			{
				using (ZipOutputStream zipOutputStream = new ZipOutputStream(zipStream))
				{
					zipOutputStream.Password = password;//设置密码
					zipOutputStream.SetComment(comment);//添加注释
					zipOutputStream.SetLevel(CheckCompressionLevel(compressionlevel));//设置压缩等级

					foreach (FileEntry fileEntry in fileEntryList)//从List取文件添加到压缩文件
					{
						if (fileEntry.IsDirectory)
						{
							ZipEntry zipEntry = new ZipEntry(fileEntry.ZipEntryName + @"\");
							zipOutputStream.PutNextEntry(zipEntry);
						}
						else
						{
							using (FileStream fileStream = File.OpenRead(fileEntry.FullName))
							{
								ZipEntry zipEntry = new ZipEntry(fileEntry.ZipEntryName);
								zipEntry.DateTime = fileEntry.LastWriteTime;
								zipEntry.Size = fileEntry.Length;
								zipOutputStream.PutNextEntry(zipEntry);

								byte[] buffer = new byte[BufferSize];
								int read = 0;
								while ((read = fileStream.Read(buffer, 0, BufferSize)) > 0)
								{
									zipOutputStream.Write(buffer, 0, read);
								}
							}
						}
					}

					//
					zipOutputStream.Flush();
				}
			}

			//
			result = zipfilepath;
		}
		catch (System.Exception ex)
		{
			if (File.Exists(zipfilepath))
			{
				File.Delete(zipfilepath);
			}
			throw new Exception("压缩失败!", ex);
		}

		return result;
	}

	public static string Decomparess(string zipfilepath, string destinationdirectory = null, string password = null)
	{
		string result = null;

		//
		if (string.IsNullOrWhiteSpace(zipfilepath))
		{
			throw new Exception("待解压缩文件[{zipfilepath}]不能为空、NULL或空白字符!");
		}
		//
		if (!File.Exists(zipfilepath))
		{
			throw new FileNotFoundException($"待解压缩文件[{zipfilepath}]在存储设备上不存在!");
		}

		//
		if (string.IsNullOrWhiteSpace(destinationdirectory))
		{
			FileInfo fileInfo = new FileInfo(zipfilepath);
			string directory = fileInfo.DirectoryName + @"\";
			string filename = fileInfo.Name.Substring(0, fileInfo.Name.Length - fileInfo.Extension.Length);

			destinationdirectory = directory + filename + @"\";
		}

		try
		{
			//
			if (!Directory.Exists(destinationdirectory))
			{
				Directory.CreateDirectory(destinationdirectory);
			}

			//
			using (FileStream zipFileStream = File.OpenRead(zipfilepath))
			{
				using (ZipInputStream zipInputStream = new ZipInputStream(zipFileStream))
				{
					zipInputStream.Password = password;

					ZipEntry zipEntry;
					while ((zipEntry = zipInputStream.GetNextEntry()) != null)
					{
						//如果是文件夹则创建
						if (zipEntry.IsDirectory)
						{
							Directory.CreateDirectory(Path.Combine(destinationdirectory, Path.GetDirectoryName(zipEntry.Name)));
						}
						//如果是文件则创建
						else
						{
							string fileName = Path.GetFileName(zipEntry.Name);
							if (!string.IsNullOrEmpty(fileName) && fileName.Trim().Length > 0)
							{
								FileInfo fileInfo = new FileInfo(Path.Combine(destinationdirectory, zipEntry.Name));

								using (FileStream fileStream = fileInfo.Create())
								{
									byte[] buffer = new byte[BufferSize];
									int read = 0;
									while ((read = zipInputStream.Read(buffer, 0, BufferSize)) > 0)
									{
										fileStream.Write(buffer, 0, read);
									}

									//
									fileStream.Flush();
								}

								//
								fileInfo.LastWriteTime = zipEntry.DateTime;
							}
						}
					}
				}
			}

			//
			result = destinationdirectory;
		}
		catch (System.Exception ex)
		{
			if (Directory.Exists(destinationdirectory))
			{
				Directory.Delete(destinationdirectory, true);
			}

			throw new Exception("解压缩发生错误!", ex);
		}

		return result;
	}
	
	public static string CompressAdd2(string zipfilepath, IEnumerable<string> sourcepathlist, string zipdirpath = null, string password = null)
    {
        string result = null;

        try
        {
            //
            if (string.IsNullOrWhiteSpace(zipfilepath))
            {
                throw new Exception("压缩文件[{zipfilepath}]不能为空、NULL或空白字符!");
            }
            //
            if (!File.Exists(zipfilepath))
            {
                throw new FileNotFoundException($"压缩文件[{zipfilepath}]在存储设备上不存在!");
            }

            //
            if (sourcepathlist == null || !(sourcepathlist.Count() > 0))
            {
                throw new Exception("待添加到压缩包的全路径文件或文件夹列表不能为空、NULL或空白字符!");
            }
            //
            foreach (string sourcepath in sourcepathlist)
            {
                if (string.IsNullOrWhiteSpace(sourcepath))
                {
                    throw new Exception("待添加到压缩包的全路径文件或文件夹列表中的元素不能为空、NULL或空白字符!");
                }

                if (!(File.Exists(sourcepath) || Directory.Exists(sourcepath)))
                {
                    throw new Exception($"待添加到压缩包的全路径文件或文件夹列表中元素[{sourcepath}]在存储设备上不存在!");
                }
            }

            //
            if (string.IsNullOrWhiteSpace(zipdirpath))
            {
                zipdirpath = null;
            }
            else
            {
                if (!zipdirpath.EndsWith(@"\"))
                {
                    zipdirpath = zipdirpath + @"\";
                }
            }

            //获取文件、文件夹列表
            List<FileEntry> fileEntryList = GetFileEntry(sourcepathlist);

            //将文件添加到已有zip文件中
            using (ZipFile zip = new ZipFile(zipfilepath))
            {
                //当前添加文件的密码,一个ZIP中,不同文件可以设置不同的密码
                //zip.Password = password;
                //更新压缩档的注释(全局)
                //zip.SetComment("1");

                zip.BeginUpdate();

                foreach (FileEntry fileEntry in fileEntryList)
                {
                    if (fileEntry.IsDirectory)
                    {
                        //zip.Add(new ZipEntry((zipdirpath != null ? zipdirpath : "") + fileEntry.ZipEntryName + @"\") { Size = 0, CompressedSize = 0, CompressionMethod = CompressionMethod.Deflated });
                        zip.AddDirectory((zipdirpath != null ? zipdirpath : "") + fileEntry.ZipEntryName + @"\");
                    }
                    else
                    {
                        //zip.Add(fileEntry.FullName, (zipdirpath != null ? zipdirpath : "") + fileEntry.ZipEntryName);
                        zip.Add(new StaticDataSource(fileEntry.FullName), new ZipEntry((zipdirpath != null ? zipdirpath : "") + fileEntry.ZipEntryName) { DateTime = fileEntry.LastWriteTime, Size = fileEntry.Length, CompressionMethod = CompressionMethod.Deflated });
                    }
                }
                zip.CommitUpdate();
            }

            //
            result = zipfilepath;
        }
        catch (System.Exception ex)
        {
            throw new Exception("压缩包添加文件失败!", ex);
        }

        return result;
    }
}

}

string[] filepaths = new string[] {
@"C:\bill\d0d76d40-617b-496a-81e5-3105eae7b723.jpg",
@"C:\bill\caf4e9b1-0232-4f0e-bf57-d31396ea73e9.jpg",
@"C:\bill\tttt",
@"C:\ball"
};

Step 2:
string zip = SoluM.Utils.Zip.ZipHelper.Compress(filepaths, null, "11111111111111", "123456");
Process.Start("explorer.exe", "/select, " + zip);
string dezip = SoluM.Utils.Zip.ZipHelper.Decomparess(zip, @"C:\zipDe", "123456");

Step 3:
string zip2 = SoluM.Utils.Zip.ZipHelper.CompressAdd(zippath3, new string[] {
@"C:\bill\培训签到1.jpg",
@"C:\bill\培训签到2.jpg",
@"C:\bill\培训签到3.jpg",
@"C:\HP_LaserJet_Pro_MFP_M426-M427"
}, @"ball\1\2", null);

Step 4:
SoluM.Utils.Zip.ZipHelper.Decomparess(zip2, null, "123456");
--Here,while ((zipEntry = zipInputStream.GetNextEntry()) != null),throw “Stored, but compressed != uncompressed”

Expected behavior

Fix the bug。

Operating System

Windows

Framework Version

.NET Framework 4.x

Tags

ZIP

Additional context

No response

@Luohui109 Luohui109 added the bug label Nov 14, 2024
@github-actions github-actions bot added the zip Related to ZIP file format label Nov 14, 2024
@SourceproStudio
Copy link

SourceproStudio commented Nov 14, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug zip Related to ZIP file format
Projects
None yet
Development

No branches or pull requests

2 participants