'Adding a directory to an existing .zip file

First of all I would like to say that i've tried looking for the solution to this and I haven't found one where I don't have to unzip, add my folder and then zip again. I am not using any third party libraries. I would like to do this using system.io.compression if it's possible at all ... If not I would use dotnetzip as my last resort.

TL;DR. I want to be able to add directories with files in them to an already created zip file. Is this possible using the System.Io.Compression library ?

EDIT:

using (FileStream zipToOpen = new FileStream(zipfile, FileMode.Open))
{
    using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update))
    {
        ZipArchiveEntry readmeEntry = archive.CreateEntry("testFolder/");
    }
}

So, using this code I am able to create a folder inside but it will be without any files in it. My question now is do I have to run this code again to get every file from my source folder to this folder inside the zip or is there a better way?



Solution 1:[1]

I managed to find a way to do this thanks to @stuartd. He pointed me to this answer https://stackoverflow.com/a/22339337/3182972 and I found a way to implement it into my code that creates directories with files inside them from a source location of said directories.

Here is the code:

   using (FileStream zipToOpen = new FileStream("c:\MyDestination\test.zip", FileMode.Open))
      {
        using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update))
          {
             ZipArchiveEntry readmeEntry;
             DirectoryInfo d = new DirectoryInfo(c:\MySourceFolder);
             FileInfo[] Files = d.GetFiles("*");
             foreach (FileInfo file in Files)
             {
               readmeEntry = archive.CreateEntryFromFile("c:\MySourceFolder"+ "\\" + file.Name, "MySourceFolder" + "/" + file.Name);
             }
          }
      }

So what I did was go to my source directory and went through all of the files that are there and with a foreach cycle I added them to the destination folder in the zip file.

You can also get the source directory name with this code:

string sourcepath = "C:\MySourceFolder";
int ind = sourcepath.LastIndexOf("\\") + 1;
string folderName = sourcepath.Substring(ind, folder.Length - ind);

Solution 2:[2]

This code is ready to go in C# 4.5 + with System.IO.Compression referenced (and having it in using clauses), it is a slight improvement of previous answer in that it encapsules the work in a function.

    public static void AddDirToZip(string source, string targetzip)
    {
        using (FileStream zipToOpen = new FileStream(targetzip, FileMode.Open))
        {
            using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update))
            {
                ZipArchiveEntry readmeEntry;
                DirectoryInfo d = new DirectoryInfo(source);
                FileInfo[] Files = d.GetFiles("*");
                foreach (FileInfo file in Files)
                {
                    readmeEntry = archive.CreateEntryFromFile(file.FullName, d.Name + "/" + file.Name);
                }
            }
        }
    }

Solution 3:[3]

This can be performed this way:

var targetDir = @"D:\test";
var zipFile = @"D:\test.zip"; 
using (ZipArchive zipArchive = ZipFile.Open(zipFile, ZipArchiveMode.Read)) 
      zipArchive.AddDirectory(targetDir, "test");



public static class ExtensionMethods;
    {

        public static void AddDirectory(this ZipArchive zip, string targetDir, string subDir = null, CompressionLevel compressionLevel = CompressionLevel.Optimal)
        {
            var ogrDir = targetDir.Replace("/", "\\");
            if (!ogrDir.EndsWith("\\"))
                ogrDir = ogrDir + "\\";

            if (subDir == null)
                subDir = "";
            else
            {
                subDir = subDir.Replace("/", "\\");
                if (subDir.StartsWith("\\"))
                    subDir = subDir.Remove(0, 1);

                if (!subDir.EndsWith("\\"))
                    subDir = subDir + "\\";
            }
            Action<string> AddDirectoryAndSubs = null;
            AddDirectoryAndSubs = delegate (string _targetDir)
            {
                string[] files = Directory.GetFiles(_targetDir);
                foreach (string file in files)
                {
                    var fileInfo = new FileInfo(file);
                    zip.CreateEntryFromFile(fileInfo.FullName, subDir + (fileInfo.Directory.ToString() + "\\").Replace(ogrDir, "") + fileInfo.Name, compressionLevel);
                }

                string[] dirs = Directory.GetDirectories(_targetDir);
                foreach (string dir in dirs)
                    AddDirectoryAndSubs(dir);
            };

            AddDirectoryAndSubs(targetDir);
        }

    }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Community
Solution 2 TaW
Solution 3 Bsquare ℬℬ