using GozareshgirProgramManager.Application.Services.FileManagement; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; namespace GozareshgirProgramManager.Infrastructure.Services.FileManagement; /// /// سرویس ذخیره‌سازی فایل در سیستم فایل محلی /// public class LocalFileStorageService : IFileStorageService { private readonly string _uploadBasePath; private readonly string _baseUrl; public LocalFileStorageService(IConfiguration configuration, IHttpContextAccessor httpContextAccessor, IHostEnvironment env) { // محاسبه مسیر پایه: اگر env نبود، از مسیر فعلی استفاده کن var contentRoot = env.ContentRootPath; _uploadBasePath = Path.Combine(contentRoot, "Storage"); // Base URL برای دسترسی به فایل‌ها var request = httpContextAccessor.HttpContext?.Request; if (request != null) { _baseUrl = $"{request.Scheme}://{request.Host}/storage"; } else { _baseUrl = configuration["FileStorage:BaseUrl"] ?? "http://localhost:5000/storage"; } // ایجاد پوشه اگر وجود نداشت if (!Directory.Exists(_uploadBasePath)) { Directory.CreateDirectory(_uploadBasePath); } } public async Task<(string StoragePath, string StorageUrl)> UploadAsync( Stream fileStream, string uniqueFileName, string category) { // ایجاد پوشه دسته‌بندی (مثلاً: Uploads/TaskChatMessage) var categoryPath = Path.Combine(_uploadBasePath, category); if (!Directory.Exists(categoryPath)) { Directory.CreateDirectory(categoryPath); } // ایجاد زیرپوشه بر اساس تاریخ (مثلاً: Uploads/TaskChatMessage/2026/01) var datePath = Path.Combine(categoryPath, DateTime.Now.Year.ToString(), DateTime.Now.Month.ToString("00")); if (!Directory.Exists(datePath)) { Directory.CreateDirectory(datePath); } // مسیر کامل فایل var storagePath = Path.Combine(datePath, uniqueFileName); // ذخیره فایل await using var fileStreamOutput = new FileStream(storagePath, FileMode.Create, FileAccess.Write); await fileStream.CopyToAsync(fileStreamOutput); // URL فایل var relativePath = Path.GetRelativePath(_uploadBasePath, storagePath) .Replace("\\", "/"); var storageUrl = $"{_baseUrl}/{relativePath}"; return (storagePath, storageUrl); } public Task DeleteAsync(string storagePath) { if (File.Exists(storagePath)) { File.Delete(storagePath); } return Task.CompletedTask; } public Task GetFileStreamAsync(string storagePath) { if (!File.Exists(storagePath)) { return Task.FromResult(null); } var stream = new FileStream(storagePath, FileMode.Open, FileAccess.Read, FileShare.Read); return Task.FromResult(stream); } public Task ExistsAsync(string storagePath) { return Task.FromResult(File.Exists(storagePath)); } public string GetFileUrl(string storagePath) { var relativePath = Path.GetRelativePath(_uploadBasePath, storagePath) .Replace("\\", "/"); return $"{_baseUrl}/{relativePath}"; } }