Jacob Alley Jacob Alley - 3 months ago 20
C# Question

Create an archive inside of an archive in C# with ZipArchive class

As the title says, I am trying to create a zip inside of a zip.

I have a zip archive created at a variable called "TargetFilePath"

var projectDirectoryPath = currentProjectViewModel.DirectoryPath;
ZipFile.CreateFromDirectory(projectDirectoryPath, TargetFilePath+@"/Project.zip");


The above will not work, I am assuming because the path c:\test.zip\project.zip is not a valid path.

edit for clarity: i literally want to zip up some files and place that zip inside of another archive. It has to be using System.IO.Compression, no 3rd party methods.

From my understanding you have to create a target address for the zip files, and,also from my experience, that target address cannot be an invalid path such as "c:\test.zip\project.zip"

Answer

The easiest way is to create your zip file in a temporary file with the contents of your projectDirectoryPath and once that is done you add that file to your target zip archive.

So basically something like this:

var projectDirectoryPath = currentProjectViewModel.DirectoryPath;
var tempFile = System.IO.Path.GetTempFileName();
try
{
    ZipFile.CreateFromDirectory(projectDirectoryPath, tempFile);

    using (var archive = ZipFile.Open(TargetFilePath, ZipArchiveMode.Update))
    {
        archive.CreateEntryFromFile(tempFile, "Project.zip", CompressionLevel.NoCompression);
    }
}
finally
{
    System.IO.File.Delete(tempFile);
}

I suggest you use CompressionLevel.NoCompression because the zip archive is already compressed and another layer of compression will add no value to it. Using ZipArchiveMode.Update when opening the archive is important so the zip file is actually altered. The other values for this enumerator are used to create a new archive from scratch or to open it as read-only.

In the example I used the CreateEntryFromFile function. It is a extension method so make sure you have the namespace in the using declarations.

It is possible to implement this in a way so no temporary file is required, but that requires a lot more code, as you have to create the new zip file yourself and write it directly to the stream you get when creating a new entry in the achive. But for most cases the example I gave should do the job.

Comments