using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; public static class Zip { // ============================================================ // UTILIDADES // ============================================================ private static string CrearDirectorioTemporal() { string dir; do { dir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); } while (Directory.Exists(dir)); Directory.CreateDirectory(dir); return dir; } private static void ObtenerFicherosRecursivo(string ruta, List lista) { lista.AddRange(Directory.GetFiles(ruta)); foreach (var dir in Directory.GetDirectories(ruta)) { ObtenerFicherosRecursivo(dir, lista); } } // ============================================================ // EXTRACCIÓN // ============================================================ public static void ExtraerArchivo(byte[] zipBytes, string nombreInterno, string destino) { using (var ms = new MemoryStream(zipBytes)) { ExtraerArchivo(ms, nombreInterno, destino); } } public static void ExtraerArchivo(Stream zipStream, string nombreInterno, string destino) { using (var zip = new ZipArchive(zipStream, ZipArchiveMode.Read, false)) { var entry = zip.GetEntry(nombreInterno); if (entry == null) throw new FileNotFoundException("El archivo '" + nombreInterno + "' no existe dentro del ZIP."); string dirTemp = CrearDirectorioTemporal(); string tempFile = Path.Combine(dirTemp, Path.GetFileName(nombreInterno)); entry.ExtractToFile(tempFile, true); if (Directory.Exists(destino)) destino = Path.Combine(destino, Path.GetFileName(nombreInterno)); if (File.Exists(destino)) File.Delete(destino); File.Move(tempFile, destino); } } public static byte[] ExtraerArchivoABytes(byte[] zipBytes, string nombreInterno) { using (var ms = new MemoryStream(zipBytes)) { return ExtraerArchivoABytes(ms, nombreInterno); } } public static byte[] ExtraerArchivoABytes(Stream zipStream, string nombreInterno) { using (var zip = new ZipArchive(zipStream, ZipArchiveMode.Read, false)) { var entry = zip.GetEntry(nombreInterno); if (entry == null) throw new FileNotFoundException("El archivo '" + nombreInterno + "' no existe dentro del ZIP."); using (var entryStream = entry.Open()) using (var output = new MemoryStream()) { entryStream.CopyTo(output); return output.ToArray(); } } } public static void ExtraerArchivo(string zipPath, string nombreInterno, string destino) { using (var fs = File.OpenRead(zipPath)) { ExtraerArchivo(fs, nombreInterno, destino); } } public static void ExtraerTodo(string zipPath, string destino, bool eliminarDestino = false) { if (eliminarDestino && Directory.Exists(destino)) Directory.Delete(destino, true); if (!Directory.Exists(destino)) Directory.CreateDirectory(destino); // En netstandard2.0 solo está ExtractToDirectory(string, string) ZipFile.ExtractToDirectory(zipPath, destino); } public static void ExtraerTodo(Stream zipStream, string destino, bool eliminarDestino = false) { if (eliminarDestino && Directory.Exists(destino)) Directory.Delete(destino, true); if (!Directory.Exists(destino)) Directory.CreateDirectory(destino); using (var zip = new ZipArchive(zipStream, ZipArchiveMode.Read, false)) { foreach (var entry in zip.Entries) { string fullPath = Path.Combine(destino, entry.FullName); string dir = Path.GetDirectoryName(fullPath); if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) Directory.CreateDirectory(dir); if (string.IsNullOrEmpty(entry.Name)) continue; // directorio entry.ExtractToFile(fullPath, true); } } } // ============================================================ // COMPRESIÓN // ============================================================ public static byte[] ComprimirArchivos(Dictionary archivos) { string tempZip = Path.GetTempFileName(); using (var zip = ZipFile.Open(tempZip, ZipArchiveMode.Create)) { foreach (var kv in archivos) { var entry = zip.CreateEntry(kv.Key, CompressionLevel.Optimal); using (var entryStream = entry.Open()) { byte[] data = kv.Value; entryStream.Write(data, 0, data.Length); } } } byte[] resultado = File.ReadAllBytes(tempZip); try { File.Delete(tempZip); } catch { } return resultado; } public static byte[] ComprimirArchivos(Dictionary archivos) { string tempZip = Path.GetTempFileName(); using (var zip = ZipFile.Open(tempZip, ZipArchiveMode.Create)) { foreach (var kv in archivos) { var entry = zip.CreateEntry(kv.Key, CompressionLevel.Optimal); using (var entryStream = entry.Open()) { kv.Value.CopyTo(entryStream); } } } byte[] resultado = File.ReadAllBytes(tempZip); try { File.Delete(tempZip); } catch { } return resultado; } // ============================================================ // AÑADIR ARCHIVOS (RECREANDO ZIP) // ============================================================ public static void AñadirArchivo(string zipPath, string archivoOrigen, string nombreDestino) { string tempZip = Path.GetTempFileName(); using (var zipNuevo = ZipFile.Open(tempZip, ZipArchiveMode.Create)) { if (File.Exists(zipPath)) { using (var zipViejo = ZipFile.Open(zipPath, ZipArchiveMode.Read)) { foreach (var entry in zipViejo.Entries) { if (entry.FullName.Equals(nombreDestino, StringComparison.OrdinalIgnoreCase)) continue; var nueva = zipNuevo.CreateEntry(entry.FullName, CompressionLevel.Optimal); using (var src = entry.Open()) using (var dst = nueva.Open()) { src.CopyTo(dst); } } } } var nuevo = zipNuevo.CreateEntry(nombreDestino, CompressionLevel.Optimal); using (var origen = File.OpenRead(archivoOrigen)) using (var destino = nuevo.Open()) { origen.CopyTo(destino); } } File.Copy(tempZip, zipPath, true); try { File.Delete(tempZip); } catch { } } // ============================================================ // COMPRIMIR DIRECTORIO // ============================================================ public static void ComprimirDirectorio(string directorio, string zipPath) { if (File.Exists(zipPath)) File.Delete(zipPath); ZipFile.CreateFromDirectory(directorio, zipPath, CompressionLevel.Optimal, false); } }