using Massenger.Server.Data.Entities; namespace Massenger.Server.Infrastructure.Storage; public sealed class AttachmentStorageService(IWebHostEnvironment environment) { private readonly string _rootPath = Path.Combine(environment.ContentRootPath, "Data", "Attachments"); public async Task SaveAsync(Guid messageId, IFormFile file, CancellationToken cancellationToken) { if (file.Length <= 0) { throw new InvalidOperationException("Attachment is empty."); } Directory.CreateDirectory(_rootPath); var attachmentId = Guid.NewGuid(); var extension = Path.GetExtension(file.FileName); var year = DateTime.UtcNow.ToString("yyyy"); var month = DateTime.UtcNow.ToString("MM"); var targetDirectory = Path.Combine(_rootPath, year, month); Directory.CreateDirectory(targetDirectory); var storedFileName = $"{attachmentId:N}{extension}"; var physicalPath = Path.Combine(targetDirectory, storedFileName); await using (var source = file.OpenReadStream()) await using (var target = File.Create(physicalPath)) { await source.CopyToAsync(target, cancellationToken); } return new MessageAttachment { Id = attachmentId, MessageId = messageId, OriginalFileName = string.IsNullOrWhiteSpace(file.FileName) ? "attachment" : Path.GetFileName(file.FileName), ContentType = string.IsNullOrWhiteSpace(file.ContentType) ? "application/octet-stream" : file.ContentType, FileSizeBytes = file.Length, StoragePath = physicalPath, UploadedAt = DateTimeOffset.UtcNow }; } public void DeleteIfExists(string? physicalPath) { if (!string.IsNullOrWhiteSpace(physicalPath) && File.Exists(physicalPath)) { File.Delete(physicalPath); } } }