Use SharpZipLib to compress the entire directory (i.e. generate a storage directory in the compressed file) [This can be easily achieved using the built-in ZipFile.CreateFromDirectory starting from .Net4.5]

In projects starting from .Net 4.5, we can introduce the System.IO.Compression and System.IO.Compression.FileSystem (required to use the static class ZipFile) assemblies In this case, it is easy to compress the entire directory using the following static method:

ZipFile.CreateFromDirectory //Note that the System.IO.Compression.FileSystem assembly needs to be introduced

For projects before .Net 4.5, third-party compression libraries such as SharpZipLib and DotNetZip are generally used to compress files. However, SharpZipLib does not seem to provide a direct method for directly compressing directories, but in fact, when adding a compressed file, the file is specified to be stored in the compressed document. The entry position (expressed in the directory hierarchy) can also achieve the purpose of compressing the entire directory (DotNetZip seems to provide it, and reference examples and sources will be given at the end of this article. This method has not been practiced).

1. The following is the complete class code based on the method of generating hierarchical directories in compressed documents based on SharpZipLib:

public class Zip
{
    /// <summary>
    /// Create compression object
    /// </summary>
    /// <param name="targetFile">Target file</param>
    /// <returns></returns>
    public static ZipOutputStream CreateZip(string targetFile)
    {
        Directory.CreateDirectory(Path.GetDirectoryName(targetFile));
        var s = new ZipOutputStream(File.Create(targetFile));
        s.SetLevel(6);
        return s;
    }

    /// <summary>
    /// Close the compressed object
    /// </summary>
    /// <param name="zip"></param>
    public static void CloseZip(ZipOutputStream zip)
    {
        zip.Finish();
        zip.Close();
    }

    /// <summary>
    /// Compress the file and generate a hierarchical directory within the compressed document.
    /// </summary>
    /// <param name="s">Compressed file stream</param>
    /// <param name="sourceFile">Not empty, file to be compressed</param>
    /// <param name="zipIncludedFolder"> can be empty. The target location in the compressed folder (for example: "folder1\subfolder1\sub_subfolder1_1") will be generated if the directories passed by the directory hierarchy do not exist in the compressed document. If empty Then put it directly in the root location of the compressed folder)</param>
    public static bool Compress(ZipOutputStream s, string sourceFile, string zipIncludedFolder)
    {
        if(s==null)
        {
            throw new FileNotFoundException("The compressed file stream cannot be empty");
        }
        if (!File.Exists(sourceFile))
        {
            throw new FileNotFoundException(string.Format("File '{0}' ", sourceFile));
        }
        using (FileStream fs = File.OpenRead(sourceFile))
        {
            ZipEntry entry = null;
            if (string.IsNullOrWhiteSpace(zipIncludedFolder))
            {
                entry = new ZipEntry(Path.GetFileName(sourceFile));
            }
            else
            {
                entry = new ZipEntry(Path.Combine(zipIncludedFolder, Path.GetFileName(sourceFile)));
            }
            var buffer = File.ReadAllBytes(sourceFile);
            entry.DateTime = DateTime.Now;
            s.PutNextEntry(entry);
            s.Write(buffer, 0, buffer.Length);
        }
        return true;
    }

    /// <summary>
    /// unzip
    /// </summary>
    /// <param name="sourceFile">Compressed document source file</param>
    /// <param name="targetPath">The target folder path after decompression</param>
    public static bool Decompress(string sourceFile, string targetPath)
    {
        if (!File.Exists(sourceFile))
        {
            throw new FileNotFoundException(string.Format("File '{0}' ", sourceFile));
        }
        if (!Directory.Exists(targetPath))
        {
            Directory.CreateDirectory(targetPath);
        }
        using (ZipInputStream s = new ZipInputStream(File.OpenRead(sourceFile)))
        {
            ZipEntry theEntry;
            while ((theEntry = s.GetNextEntry()) != null)
            {
                string directorName = Path.Combine(targetPath, Path.GetDirectoryName(theEntry.Name));
                string fileName = Path.Combine(directorName, Path.GetFileName(theEntry.Name));
                if (directorName.Length > 0)
                {
                    Directory.CreateDirectory(directorName);
                }
                if (!string.IsNullOrWhiteSpace(fileName))
                {
                    using (FileStream streamWriter = File.Create(fileName))
                    {
                        int size = (int)theEntry.Size;
                        byte[] data = new byte[size];
                        size = s.Read(data, 0, data.Length);
                        if (size > 0)
                        {
                            streamWriter.Write(data, 0, size);
                        }
                    }
                }
            }
        }
        return true;
    }
}

2. Use the above class to compress the entire directory:

public void Example()
{
    var zipFile = @"D:\temp\ZipStore\testZipFileName.zip";
    var zipStream = Zip.CreateZip(zipFile);

    //Test the "source directory file" and "the hierarchical directory location to be stored in the compressed package":
    var filesToZip = new List<Tuple<string, string>>();
    var file1 = @"D:\temp\ZipTest\Physical Examination\TestSub\Attachment 5: Family Physical Examination Information Form.xlsx";
    var pathInZip1 = @"Physical examination\TestSub";
    filesToZip.Add(Tuple.Create(file1, pathInZip1));
    var file2 = @"D:\temp\ZipTest\Physical Examination\TestSub\1111\Attachment 5: Family Physical Examination Information Form.xlsx";
    var pathInZip2 = @"Physical examination\TestSub\1111";
    filesToZip.Add(Tuple.Create(file2, pathInZip2));
    var file3 = @"D:\temp\ZipTest\Physical Examination 2\TestSub\1111\TestSub\sfssfs.txt";
    var pathInZip3 = @"Physical examination 2\TestSub\1111\TestSub";
    filesToZip.Add(Tuple.Create(file3, pathInZip3));

    /*
     *The above is just for visual effect,
     * In practice, the following method should be used to obtain all files in the source directory to be added to the compressed package:
     * Directory.GetFiles(entireFolderPath, "*.*", SearchOption.AllDirectories)
     * And for all files, use the following method to match the hierarchical directory location where the files are to be stored in the compressed package according to the file path:
     * Path.GetDirectoryName("<Remove the source folder location prefix, corresponding to the file path starting from the hierarchical directory in the compressed package>")
     */

    filesToZip.ForEach(tupFileInfo =>
    {
        Zip.Compress(zipStream, tupFileInfo.Item1, tupFileInfo.Item2);
    });

    zipStream.Close();
}

The test effect is as follows:

Attachment: DotNetZip compression folder method (not verified in practice):

Introduce DotNetZip DLL and refer to the following code:

string[] MainDirs = Directory.GetDirectories(""c:\users\public\reports");

for (int i = 0; i < MainDirs.Length; i + + )
{
    using (ZipFile zip = new ZipFile())
    {
        zip.UseUnicodeAsNecessary = true;
        zip.AddDirectory(MainDirs[i]);
        zip.CompressionLevel = Ionic.Zlib.CompressionLevel.BestCompression;
        zip.Comment = "This zip was created at " + System.DateTime.Now.ToString("G");
        zip.Save(string.Format("test{0}.zip", i));
    }
}

Reference materials:

1. SharpZipLib compressed folder:

https://www.zhankr.net/40888.html

2. DotNetZip compressed folder (
DotNetZip source code: https://github.com/haf/DotNetZip.Semverd
):

https://www.coder.work/article/1652646
(Translated from: https://stackoverflow.com/questions/20451073/zip-complete-folder-using-system-io-compression)

However, the statement in the source that “System.IO.Compression cannot compress a complete folder” is incorrect at the moment. As mentioned at the beginning of this article, System.IO comes with System.IO after .Net 4.5. .Compression assembly, you only need to introduce the System.IO.Compression.FileSystem assembly at the same time to easily compress and package the entire directory.

[Another related article]: C# implements compression and decompression scheme_c# decompression-CSDN blog