using System; using System.IO; using System.IO.Compression; namespace Alkami.Ops.Common.FileSystem { public static class ZipHelpers { /// /// Unzip a path into a specific folder /// /// Path of the file to unzip. /// If null defaults to a new folder at current location with the Zip file's name. public static void UnZip(string zipPath, string destinationDirectory = null) { if (!string.IsNullOrWhiteSpace(zipPath)) { if (string.IsNullOrWhiteSpace(destinationDirectory)) { destinationDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); destinationDirectory = Path.Combine(destinationDirectory, Path.GetFileNameWithoutExtension(zipPath)); } Directory.CreateDirectory(destinationDirectory); try { using (var archive = ZipFile.OpenRead(zipPath)) { archive.ExtractToDirectory(destinationDirectory); } } catch (IOException ex) { Console.Error.WriteLine("Exception occurred while extracting files."); Console.Error.WriteLine(ex); } } } /// /// Unzips a single directory from inside a zip file. /// /// Path of the file to unzip. /// Directory inside of zip file to be extracted. If null or nonexistent nothing will be extracted. /// If null defaults to a new folder at current location with the Zip subfolder's name. public static void UnZipSubDirectory(string internalDirectory, string zipPath, string destinationDirectory = null) { if (!string.IsNullOrWhiteSpace(zipPath)) { if (string.IsNullOrWhiteSpace(destinationDirectory)) { destinationDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); destinationDirectory = Path.Combine(destinationDirectory, Path.GetFileNameWithoutExtension(zipPath)); } Directory.CreateDirectory(destinationDirectory); try { using (var archive = ZipFile.OpenRead(zipPath)) { foreach (var entry in archive.Entries) { if (GetRootFolder(entry.FullName).IndexOf(internalDirectory, StringComparison.OrdinalIgnoreCase) >= 0) { ExtractEntry(entry, destinationDirectory, entry.FullName); } } } } catch (IOException ex) { Console.Error.WriteLine("Exception occurred while extracting files."); Console.Error.WriteLine(ex); } catch (Exception ex) { Console.Error.WriteLine("Unknown exception occurred while extracting files"); Console.Error.WriteLine(ex); throw; } } } /// /// Recursively handle subfolders /// /// Zip entry to extract /// Desired destination directory. Is added to with each recursive loop as subdirectories are popped off of the entry /// Current entry path. Shorter every loop as we pop off directories and add them to the destinationDirectory parameter. private static void ExtractEntry(ZipArchiveEntry entry, string destinationDirectory, string entryPath) { var targetIsDirectory = false; var topLevelDirectory = ""; if (!string.IsNullOrWhiteSpace(entryPath) && !entryPath.Equals('/')) { topLevelDirectory = Path.GetDirectoryName(entryPath); } else { targetIsDirectory = true; } if (!string.IsNullOrEmpty(topLevelDirectory)) { Directory.CreateDirectory(Path.Combine(destinationDirectory, topLevelDirectory)); destinationDirectory = Path.Combine(destinationDirectory, topLevelDirectory); ExtractEntry(entry, destinationDirectory, Path.GetFileName(entryPath)); } else { if (targetIsDirectory) { Directory.CreateDirectory(destinationDirectory); } else { entry.ExtractToFile(Path.Combine(destinationDirectory, entry.Name)); } } } /// /// Cargo culted from https://stackoverflow.com/a/40124633/3691973 /// /// Path to examine /// Top level folder. private static string GetRootFolder(string path) { var root = Path.GetPathRoot(path); while (true) { var temp = Path.GetDirectoryName(path); if (temp != null && temp.Equals(root)) break; path = temp; } return path; } } }