From 2cd838a5e3342a604b3dc2000283a608415f668b Mon Sep 17 00:00:00 2001 From: mahan Date: Wed, 7 Jan 2026 10:25:33 +0330 Subject: [PATCH] feat: enhance thumbnail generation with category support and update storage paths --- .../SendMessage/SendMessageCommand.cs | 3 +- .../IThumbnailGeneratorService.cs | 8 +++-- .../ThumbnailGeneratorService.cs | 33 ++++++++++++++----- ServiceHost/Program.cs | 4 +-- 4 files changed, 34 insertions(+), 14 deletions(-) diff --git a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/TaskChat/Commands/SendMessage/SendMessageCommand.cs b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/TaskChat/Commands/SendMessage/SendMessageCommand.cs index 891a60fc..245d8b39 100644 --- a/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/TaskChat/Commands/SendMessage/SendMessageCommand.cs +++ b/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/TaskChat/Commands/SendMessage/SendMessageCommand.cs @@ -106,7 +106,8 @@ public class SendMessageCommandHandler : IBaseCommandHandler Task<(string ThumbnailPath, string ThumbnailUrl)?> GenerateImageThumbnailAsync( - string imagePath, - int width = 200, + string imagePath, + string category, + int width = 200, int height = 200); /// /// تولید thumbnail برای ویدیو /// Task<(string ThumbnailPath, string ThumbnailUrl)?> GenerateVideoThumbnailAsync( - string videoPath); + string videoPath, + string category); /// /// حذف thumbnail diff --git a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/FileManagement/ThumbnailGeneratorService.cs b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/FileManagement/ThumbnailGeneratorService.cs index df55c827..85ced061 100644 --- a/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/FileManagement/ThumbnailGeneratorService.cs +++ b/ProgramManager/src/Infrastructure/GozareshgirProgramManager.Infrastructure/Services/FileManagement/ThumbnailGeneratorService.cs @@ -1,4 +1,5 @@ using GozareshgirProgramManager.Application.Services.FileManagement; +using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Processing; @@ -14,12 +15,21 @@ public class ThumbnailGeneratorService : IThumbnailGeneratorService private readonly string _thumbnailBasePath; private readonly string _baseUrl; - public ThumbnailGeneratorService(IConfiguration configuration) + public ThumbnailGeneratorService(IConfiguration configuration, + IHttpContextAccessor httpContextAccessor) { _thumbnailBasePath = configuration["FileStorage:ThumbnailPath"] - ?? Path.Combine(Directory.GetCurrentDirectory(), "Uploads", "Thumbnails"); + ?? Path.Combine(Directory.GetCurrentDirectory(), "storage", "Thumbnails"); + var request = httpContextAccessor.HttpContext?.Request; - _baseUrl = configuration["FileStorage:BaseUrl"] ?? "http://localhost:5000/uploads"; + if (request != null) + { + _baseUrl = $"{request.Scheme}://{request.Host}/storage"; + } + else + { + _baseUrl = configuration["FileStorage:BaseUrl"] ?? "http://localhost:5000/storage"; + } if (!Directory.Exists(_thumbnailBasePath)) { @@ -28,7 +38,8 @@ public class ThumbnailGeneratorService : IThumbnailGeneratorService } public async Task<(string ThumbnailPath, string ThumbnailUrl)?> GenerateImageThumbnailAsync( - string imagePath, + string imagePath, + string category, int width = 200, int height = 200) { @@ -54,14 +65,21 @@ public class ThumbnailGeneratorService : IThumbnailGeneratorService var extension = Path.GetExtension(imagePath); var thumbnailFileName = $"{fileName}_thumb{extension}"; + var categoryFolder = string.IsNullOrWhiteSpace(category) ? "general" : category; + var categoryPath = Path.Combine(_thumbnailBasePath, categoryFolder); + if (!Directory.Exists(categoryPath)) + { + Directory.CreateDirectory(categoryPath); + } + // مسیر ذخیره thumbnail - var thumbnailPath = Path.Combine(_thumbnailBasePath, thumbnailFileName); + var thumbnailPath = Path.Combine(categoryPath, thumbnailFileName); // ذخیره thumbnail با کیفیت 80 await image.SaveAsync(thumbnailPath, new JpegEncoder { Quality = 80 }); // URL thumbnail - var thumbnailUrl = $"{_baseUrl}/thumbnails/{thumbnailFileName}"; + var thumbnailUrl = $"{_baseUrl}/thumbnails/{categoryFolder}/{thumbnailFileName}"; return (thumbnailPath, thumbnailUrl); } @@ -72,7 +90,7 @@ public class ThumbnailGeneratorService : IThumbnailGeneratorService } } - public async Task<(string ThumbnailPath, string ThumbnailUrl)?> GenerateVideoThumbnailAsync(string videoPath) + public async Task<(string ThumbnailPath, string ThumbnailUrl)?> GenerateVideoThumbnailAsync(string videoPath, string category = "general") { // TODO: برای Video thumbnail باید از FFmpeg استفاده کنیم // فعلاً یک placeholder image برمی‌گردانیم @@ -108,4 +126,3 @@ public class ThumbnailGeneratorService : IThumbnailGeneratorService } } } - diff --git a/ServiceHost/Program.cs b/ServiceHost/Program.cs index 76189996..9584824e 100644 --- a/ServiceHost/Program.cs +++ b/ServiceHost/Program.cs @@ -493,7 +493,7 @@ app.UseHttpsRedirection(); app.UseStaticFiles(); // Static files برای فایل‌های آپلود شده -var uploadsPath = builder.Configuration["FileStorage:LocalPath"] ?? Path.Combine(Directory.GetCurrentDirectory(), "Uploads"); +var uploadsPath = builder.Configuration["FileStorage:LocalPath"] ?? Path.Combine(Directory.GetCurrentDirectory(), "Storage"); if (!Directory.Exists(uploadsPath)) { Directory.CreateDirectory(uploadsPath); @@ -502,7 +502,7 @@ if (!Directory.Exists(uploadsPath)) app.UseStaticFiles(new StaticFileOptions { FileProvider = new Microsoft.Extensions.FileProviders.PhysicalFileProvider(uploadsPath), - RequestPath = "/uploads", + RequestPath = "/storage", OnPrepareResponse = ctx => { // Cache برای فایل‌ها (30 روز)