Adding a directory to an existing .zip file
Asked Answered
C

3

6

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?

Chessman answered 22/7, 2016 at 10:21 Comment(6)
To be clear, are you saying you want to add just a folder, and not add any files to it or move files to it? Or are you adding a directory with files in?Upturn
I'm sorry I didn't make it clear but I want to add a directory with files in it. I will edit it right awayChessman
Does How do I add files to an existing zip archive answer your question?Upturn
I looked at this answer but I didn't know how to modify it to my needs(I tried). I just had an idea of something else I can try using this and I'll get back to you.Chessman
@Upturn I have updated my question with the code I used(which works) for creating a folder inside.Chessman
If you add files that are in the directory to the zip file, then you don't need to add the directory itself. Unzip will create the directories needed to extract the files.Lookeron
C
7

I managed to find a way to do this thanks to @stuartd. He pointed me to this answer, 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);
Chessman answered 22/7, 2016 at 13:26 Comment(0)
F
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);
            }
        }
    }
}
Finke answered 29/11, 2019 at 4:10 Comment(1)
Note that this is not recursive, so it will only add the files, not any subdirectories! - For a nicer and more complete solution see Val's extension class here!!Babylon
A
1

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);
    }
}
Adelia answered 10/12, 2018 at 8:4 Comment(1)
AddDirectoryAndSubs can (in C# 7.0) be written as a local function instead of a delegate, which avoids... ...awkward code, where you first assign null to a delegate variable... And it offers other improvements. See: https://mcmap.net/q/117163/-local-function-vs-lambda-c-7-0Effective

© 2022 - 2024 — McMap. All rights reserved.