0

How do I Zip some files and directories without a root directory in C#?

I'm currently writing a program to automatically side-load apps to a Roku over HTTP. I have successfully written all the software except for the part which zips the source files. The Roku needs to be supplied with a zip file with the source files of the app in the top level of the zips file tree. My first instinct was to use the ZipFile class like ZipFile.CreateFromDirectory(source, output);. This did compress the files and directories however, it also included the source directory as the top level of file in the zip. This means that all my source files and directories were not in the top level of file, like the Roku needs.

An other, way I tried to does this is by using the ZipArchive class / extension methods. However, with this I could not add directories to the zip, so this was also not appropriate.

To Get around this on Windows when making the zip file you must select the actual files and directories and then select Send to - Compressed (zipped) folder and Not do this on the file that contains them (an example of this is shown in bellow:

The Question:

Is there a way to compress files and directories to a zip file in c# where those files and directories will be at the top of the zip's file tree? Any help is appreciated.

Dan13_
  • 193
  • 1
  • 2
  • 16
  • Why are you writing c# code for it when this can be done by a script? E.g. for Windows, http://stackoverflow.com/questions/17546016 – Nas Banov Oct 23 '16 at 20:37
  • Good idea doing it with java from the command line works perfectly. – Dan13_ Oct 24 '16 at 11:29

1 Answers1

0

Try this:

static bool AddDirectory(this ZipArchive archive, int rootLength, string directory)
{
    bool hasFiles = false;
    foreach (var entry in Directory.GetFileSystemEntries(directory))
    {
        string relativePath = entry.Substring(rootLength);
        if (Directory.Exists(entry))
        {
            if (!archive.AddDirectory(rootLength, entry))
            {
                archive.CreateEntry(relativePath + "/");
            }
        }
        else
        {
            archive.CreateEntryFromFile(entry, relativePath);
            hasFiles = true;
        }
    }
    return hasFiles;
}

public static void AddDirectoryWithoutRoot(this ZipArchive archive, string directory)
{
    int pathRootLength = (directory.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar).Length;
    archive.AddDirectory(pathRootLength, directory);
    archive.CreateEntry("/");
}

Usage:

using (var fs = File.Create("test.zip"))
{
    ZipArchive archive = new ZipArchive(fs, ZipArchiveMode.Create);
    archive.AddDirectoryWithoutRoot(@"C:\your\path");
}
airafr
  • 332
  • 2
  • 7
  • The installer returns "Install Failure: Script directory "/source" does not exist in plugin." this occurs when the source file is not in the root directory so this did not work but thank you. – Dan13_ Oct 22 '16 at 15:26
  • @Dan13_ I have modified the code to work with empty subdirectories. – airafr Oct 22 '16 at 16:07
  • @airadr this also has the same affect. – Dan13_ Oct 23 '16 at 11:54
  • @Dan13_ I have tested the code and its result is exactly the same as if you perform the "Correct" zipping procedure shown in your question. You can test it by unzipping the file (everything will be in the root directory). – airafr Oct 23 '16 at 12:00
  • @airadr yes I have looked at them both they appear to be the same however, the plugin installer will accept the same files manually zipped the 'correct' way but not the same files zipped with the above code. – Dan13_ Oct 23 '16 at 12:08
  • @airadr if I use the usage you suggested as shown in example 1 it creates an invalid zip file. So i have been using what is shown in example 2, which works. – Dan13_ Oct 23 '16 at 12:42