using Microsoft.Extensions.Logging; namespace GSS2.Core; public class ImageStorageService { private readonly ILogger _logger; private readonly DirectoryInfo _rootDirectory; public ImageStorageService(ILogger logger, DirectoryInfo rootDirectory) { _logger = logger; _logger.LogInformation("Инициализация"); _rootDirectory = rootDirectory; if (!_rootDirectory.Exists) { _rootDirectory.Create(); _logger.LogInformation("Создана директория: {}", _rootDirectory.FullName); } _logger.LogInformation("Инициализировано"); } public async Task SaveAsync(Stream fileStream, string extension, string subDirectory, CancellationToken cancellationToken = default) { var fileName = GenerateFileName(extension); var fullPath = GetFullPath(fileName, subDirectory); System.Diagnostics.Debug.Assert(fullPath is not null); var directory = Path.GetDirectoryName(fullPath)!; Directory.CreateDirectory(directory); await using var file = new FileStream( fullPath, FileMode.CreateNew, FileAccess.Write, FileShare.None, 81920, useAsync: true); await fileStream.CopyToAsync(file, cancellationToken); _logger.LogInformation("Файл сохранён: {}", fileName); return fileName; } public Stream OpenRead(string fileName, string? subDirectory = null) { var fullPath = GetFullPath(fileName, subDirectory); if (fullPath is null) throw new FileNotFoundException(null, fullPath); return new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.Read); } public bool Delete(string fileName, string? subDirectory = null) { var fullPath = GetFullPath(fileName, subDirectory); if (fullPath is null) throw new FileNotFoundException(null, fullPath); if (!File.Exists(fullPath)) return false; File.Delete(fullPath); _logger.LogInformation("Файл удалён: {}", fileName); var parentDirectory = Directory.GetParent(fullPath); if (parentDirectory?.GetFiles().Count() == 0) { parentDirectory.Delete(); _logger.LogInformation("Удалена пустая директория: {}", parentDirectory.Name); } return true; } private string GenerateFileName(string extension) { var guid = Guid.NewGuid().ToString("N"); return $"{guid}{extension}"; } public string? GetFullPath(string fileName, string? subDirectory = null) { if (fileName.Count() < 4) return null; var level1 = fileName.Substring(0, 2); var level2 = fileName.Substring(2, 2); if (subDirectory is not null) return Path.Combine(_rootDirectory.FullName, subDirectory, level1, level2, fileName); return ListFiles() .FirstOrDefault(f => Path.GetFileName(f) == fileName); } public List ListFiles(string? subDirectory = null) { if (subDirectory is not null) return Directory.GetDirectories(Path.Join(_rootDirectory.FullName, subDirectory)) .SelectMany(Directory.GetDirectories) .SelectMany(Directory.GetFiles) .ToList(); return Directory.GetDirectories(_rootDirectory.FullName) .Select(Path.GetFileName) .SelectMany(ListFiles) .ToList(); } }