Files

157 lines
3.9 KiB
C#
Raw Permalink Normal View History

2026-08-27 10:55:23 -06:00
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Text;
namespace Intelix.Helper.Data;
public sealed class InMemoryZip : IDisposable
{
private readonly ConcurrentDictionary<string, byte[]> _entries = new ConcurrentDictionary<string, byte[]>(StringComparer.OrdinalIgnoreCase);
private readonly object _buildLock = new object();
private bool _disposed;
private string _rootFolderPrefix = string.Empty;
public int Count => _entries.Count;
public void SetRootFolderPrefix(string prefix)
{
if (string.IsNullOrEmpty(prefix))
{
_rootFolderPrefix = string.Empty;
}
else
{
_rootFolderPrefix = NormalizeEntryName(prefix) + "/";
}
}
private static string NormalizeEntryName(string name)
{
if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentException("Entry name is null or empty", "name");
}
name = name.Replace('\\', '/').Trim('/');
if (name.Length != 0)
{
return name;
}
throw new ArgumentException("Invalid entry name", "name");
}
private string ApplyRootPrefix(string entryPath)
{
if (string.IsNullOrEmpty(_rootFolderPrefix))
{
return entryPath;
}
string normalized = NormalizeEntryName(entryPath);
if (normalized.StartsWith(_rootFolderPrefix, StringComparison.OrdinalIgnoreCase))
{
return normalized;
}
return _rootFolderPrefix + normalized;
}
public void AddFile(string entryPath, byte[] content)
{
if (_disposed)
{
throw new ObjectDisposedException("InMemoryZip");
}
if (content != null && content.Length != 0)
{
string key = ApplyRootPrefix(entryPath);
byte[] copy = new byte[content.Length];
Buffer.BlockCopy(content, 0, copy, 0, content.Length);
_entries.AddOrUpdate(key, copy, (string text, byte[] old) => copy);
}
}
public void AddTextFile(string entryPath, string text)
{
if (!string.IsNullOrEmpty(text))
{
AddFile(entryPath, Encoding.UTF8.GetBytes(text));
}
}
public void AddDirectoryFiles(string sourceDirectory, string targetEntryDirectory = "", bool recursive = true)
{
if (_disposed)
{
throw new ObjectDisposedException("InMemoryZip");
}
if (string.IsNullOrEmpty(sourceDirectory))
{
throw new ArgumentException("sourceDirectory");
}
if (!Directory.Exists(sourceDirectory))
{
return;
}
SearchOption searchOption = (recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
string[] files = Directory.GetFiles(sourceDirectory, "*", searchOption);
foreach (string text in files)
{
string text2 = text.Substring(sourceDirectory.Length).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
string text3 = (string.IsNullOrEmpty(targetEntryDirectory) ? text2 : Path.Combine(targetEntryDirectory, text2));
text3 = text3.Replace('\\', '/');
try
{
byte[] content = File.ReadAllBytes(text);
AddFile(text3, content);
}
catch
{
}
}
}
public byte[] ToArray(CompressionLevel compression = CompressionLevel.Fastest)
{
if (_disposed)
{
throw new ObjectDisposedException("InMemoryZip");
}
lock (_buildLock)
{
using MemoryStream memoryStream = new MemoryStream();
using (ZipArchive zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create, leaveOpen: true, Encoding.UTF8))
{
foreach (KeyValuePair<string, byte[]> entry in _entries)
{
using Stream stream = zipArchive.CreateEntry(entry.Key, compression).Open();
byte[] value = entry.Value;
stream.Write(value, 0, value.Length);
}
}
return memoryStream.ToArray();
}
}
public IEnumerable<KeyValuePair<string, byte[]>> GetAllEntries()
{
return _entries;
}
public void Clear()
{
_entries.Clear();
}
public void Dispose()
{
if (!_disposed)
{
_disposed = true;
_entries.Clear();
}
}
}