Skip to content

Commit 29505f2

Browse files
committed
Implemented image resizing on upload. Max image size can be configured in settings.
1 parent e6b3792 commit 29505f2

File tree

8 files changed

+200
-9
lines changed

8 files changed

+200
-9
lines changed

Client/GIBS.Module.BusinessDirectory.Client.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
<Reference Include="Oqtane.Shared">
3232
<HintPath>..\..\oqtane.framework-6.1.2-Source\Oqtane.Server\bin\Debug\net9.0\Oqtane.Shared.dll</HintPath>
3333
</Reference>
34+
<Reference Include="SixLabors.ImageSharp">
35+
<HintPath>..\..\oqtane.framework-6.1.2-Source\Oqtane.Server\bin\Debug\net9.0\SixLabors.ImageSharp.dll</HintPath>
36+
</Reference>
3437
</ItemGroup>
3538

3639
<PropertyGroup>

Client/Modules/GIBS.Module.BusinessDirectory/CompanyEdit.razor

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,8 @@ else
303303
private string _returnurl = string.Empty;
304304
private string _imageUploadError;
305305
private int _folderId = 1;
306+
private int _imageMaxWidth; // Set your max width here
307+
private int _imageMaxHeight; // Set your max height here
306308
307309
public override List<Resource> Resources => new List<Resource>()
308310
{
@@ -334,6 +336,15 @@ else
334336
_folderId = 1; // Default value or handle error
335337
}
336338

339+
if (!int.TryParse(SettingService.GetSetting(ModuleState.Settings, "ImageMaxWidth", "800"), out _imageMaxWidth))
340+
{
341+
_imageMaxWidth = 800;
342+
}
343+
if (!int.TryParse(SettingService.GetSetting(ModuleState.Settings, "ImageMaxHeight", "600"), out _imageMaxHeight))
344+
{
345+
_imageMaxHeight = 600;
346+
}
347+
337348

338349
int moduleId = PageState.ModuleId /* get your ModuleId here */;
339350
ParentItems = BuildTree(await BusinessDirectoryService.GetBusinessDirectorysAsync(moduleId));
@@ -496,16 +507,59 @@ else
496507
}
497508
}
498509

510+
// private async void HandleFileUpload(int fileId)
511+
// {
512+
// if (_company != null)
513+
// {
514+
// var uploadedFile = await FileService.GetFileAsync(fileId);
515+
// if (uploadedFile != null)
516+
// {
517+
518+
// _company.ImageURL = uploadedFile.Url;
519+
520+
// }
521+
// else
522+
// {
523+
// _company.ImageURL = null;
524+
// }
525+
// StateHasChanged();
526+
// }
527+
// }
528+
499529
private async void HandleFileUpload(int fileId)
500530
{
501531
if (_company != null)
502532
{
503533
var uploadedFile = await FileService.GetFileAsync(fileId);
504534
if (uploadedFile != null)
505535
{
506-
507-
_company.ImageURL = uploadedFile.Url;
508-
536+
// Check if the image exceeds the maximum dimensions from settings
537+
if (uploadedFile.ImageWidth > _imageMaxWidth || uploadedFile.ImageHeight > _imageMaxHeight)
538+
{
539+
try
540+
{
541+
var resizedFile = await BusinessCompanyService.ResizeImageAsync(uploadedFile.FileId, _imageMaxWidth, _imageMaxHeight, ModuleState.ModuleId);
542+
if (resizedFile != null)
543+
{
544+
_company.ImageURL = resizedFile.Url;
545+
}
546+
else
547+
{
548+
// Fallback to original image if resize fails
549+
_company.ImageURL = uploadedFile.Url;
550+
AddModuleMessage("Image resizing failed. Using original image.", MessageType.Warning);
551+
}
552+
}
553+
catch (Exception ex)
554+
{
555+
AddModuleMessage($"Error resizing image: {ex.Message}", MessageType.Error);
556+
_company.ImageURL = uploadedFile.Url; // Fallback to original image
557+
}
558+
}
559+
else
560+
{
561+
_company.ImageURL = uploadedFile.Url;
562+
}
509563
}
510564
else
511565
{

Client/Modules/GIBS.Module.BusinessDirectory/Settings.razor

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,19 @@
3030
</div>
3131
</div>
3232

33+
<div class="row mb-1 align-items-center">
34+
<Label Class="col-sm-3" For="imageMaxWidth" HelpText="The maximum width for uploaded images (in pixels). The image will be resized if it exceeds this value." ResourceKey="ImageMaxWidth">Max Image Width: </Label>
35+
<div class="col-sm-9">
36+
<input id="imageMaxWidth" type="number" class="form-control" @bind="@_imageMaxWidth" />
37+
</div>
38+
</div>
39+
<div class="row mb-1 align-items-center">
40+
<Label Class="col-sm-3" For="imageMaxHeight" HelpText="The maximum height for uploaded images (in pixels). The image will be resized if it exceeds this value." ResourceKey="ImageMaxHeight">Max Image Height: </Label>
41+
<div class="col-sm-9">
42+
<input id="imageMaxHeight" type="number" class="form-control" @bind="@_imageMaxHeight" />
43+
</div>
44+
</div>
45+
3346
</div>
3447

3548
@code {
@@ -42,6 +55,8 @@
4255

4356
string _featuredCount;
4457
string _imageFolder;
58+
string _imageMaxWidth;
59+
string _imageMaxHeight;
4560

4661
protected override async Task OnInitializedAsync()
4762
{
@@ -51,6 +66,8 @@
5166
_googleApiKey = SettingService.GetSetting(settings, "GoogleApiKey", "");
5267
_featuredCount = SettingService.GetSetting(settings, "FeaturedCount", "3");
5368
_imageFolder = SettingService.GetSetting(settings, "ImageFolder", "Root");
69+
_imageMaxWidth = SettingService.GetSetting(settings, "ImageMaxWidth", "800");
70+
_imageMaxHeight = SettingService.GetSetting(settings, "ImageMaxHeight", "600");
5471
_folders = await FolderService.GetFoldersAsync(PageState.Site.SiteId);
5572
}
5673
catch (Exception ex)
@@ -67,6 +84,8 @@
6784
SettingService.SetSetting(settings, "GoogleApiKey", _googleApiKey);
6885
SettingService.SetSetting(settings, "FeaturedCount", _featuredCount);
6986
SettingService.SetSetting(settings, "ImageFolder", _imageFolder);
87+
SettingService.SetSetting(settings, "ImageMaxWidth", _imageMaxWidth);
88+
SettingService.SetSetting(settings, "ImageMaxHeight", _imageMaxHeight);
7089
await SettingService.UpdateModuleSettingsAsync(settings, ModuleState.ModuleId);
7190
}
7291
catch (Exception ex)

Client/Services/BusinessCompanyService.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,5 +128,25 @@ public async Task UpdateCompanyAttributesAsync(int companyId, int moduleId, List
128128
return new List<Models.BusinessCompany>();
129129
}
130130
}
131+
132+
public async Task<Oqtane.Models.File> ResizeImageAsync(int fileId, int width, int height, int moduleId)
133+
{
134+
var request = new { FileId = fileId, Width = width, Height = height, ModuleId = moduleId };
135+
var url = CreateAuthorizationPolicyUrl($"{Apiurl}/resize-image", EntityNames.Module, moduleId);
136+
137+
try
138+
{
139+
var response = await _httpClient.PostAsJsonAsync(url, request);
140+
response.EnsureSuccessStatusCode();
141+
return await response.Content.ReadFromJsonAsync<Oqtane.Models.File>();
142+
}
143+
catch (Exception ex)
144+
{
145+
// Log or handle exceptions as needed
146+
Console.WriteLine($"Error resizing image: {ex.Message}");
147+
return null;
148+
}
149+
}
150+
131151
}
132152
}

Server/Controllers/BusinessCompanyController.cs

Lines changed: 91 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@
55
using Microsoft.AspNetCore.Http;
66
using Microsoft.AspNetCore.Mvc;
77
using Oqtane.Controllers;
8+
using Oqtane.Enums;
89
using Oqtane.Infrastructure;
10+
using Oqtane.Repository;
11+
using Oqtane.Services;
12+
using Oqtane.Shared;
13+
using SixLabors.ImageSharp;
14+
using System;
915
using System.Collections.Generic;
1016
using System.IO;
1117
using System.Threading.Tasks;
12-
using System;
13-
using Oqtane.Shared;
14-
using Oqtane.Enums;
18+
1519

1620
namespace GIBS.Module.BusinessDirectory.Server.Controllers
1721
{
@@ -20,25 +24,30 @@ public class BusinessCompanyController : ModuleControllerBase
2024
{
2125
private readonly IBusinessCompanyRepository _businessCompanyRepository;
2226
private readonly IWebHostEnvironment _env;
23-
// private readonly IFolderRepository _folders;
27+
private readonly IFileRepository _files;
28+
private readonly IImageService _imageService;
2429

2530
public BusinessCompanyController(
2631
IBusinessCompanyRepository businessCompanyRepository,
2732
ILogManager logger,
2833
IHttpContextAccessor accessor,
29-
IWebHostEnvironment env
34+
IWebHostEnvironment env,
35+
IFileRepository files,
36+
IImageService imageService
3037
) : base(logger, accessor)
3138
{
3239
_businessCompanyRepository = businessCompanyRepository;
3340
_env = env;
41+
_files = files;
42+
_imageService = imageService;
3443
}
3544

3645
// GET: api/BusinessCompany?moduleid=x
3746
[HttpGet]
3847
[Authorize(Policy = PolicyNames.ViewModule)]
3948
public async Task<IEnumerable<BusinessCompany>> Get(string moduleid)
4049
{
41-
50+
4251
int moduleId;
4352
if (int.TryParse(moduleid, out moduleId) && IsAuthorizedEntityId(EntityNames.Module, moduleId))
4453
{
@@ -157,6 +166,74 @@ public async Task<IActionResult> UploadImage([FromForm] IFormFile file)
157166
return Ok(imageUrl);
158167
}
159168

169+
[HttpPost("resize-image")]
170+
[Authorize(Policy = PolicyNames.EditModule)]
171+
public async Task<ActionResult<Oqtane.Models.File>> ResizeImage([FromBody] ResizeRequest request)
172+
{
173+
var file = _files.GetFile(request.FileId);
174+
if (file == null || !IsAuthorizedEntityId(EntityNames.Module, request.ModuleId))
175+
{
176+
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Image Resize Attempt for FileId {FileId}", request.FileId);
177+
return Forbid();
178+
}
179+
180+
string originalFilePath = null;
181+
string tempFilePath = null;
182+
183+
try
184+
{
185+
originalFilePath = _files.GetFilePath(file);
186+
if (System.IO.File.Exists(originalFilePath))
187+
{
188+
// 1. Create a temporary path for the resized image
189+
tempFilePath = Path.ChangeExtension(originalFilePath, ".tmp" + Path.GetExtension(originalFilePath));
190+
191+
// 2. Use the IImageService to create the resized image at the temporary path
192+
var resizedImagePath = _imageService.CreateImage(originalFilePath, request.Width, request.Height, "medium", "center", "white", "", file.Extension, tempFilePath);
193+
194+
if (string.IsNullOrEmpty(resizedImagePath) || !System.IO.File.Exists(resizedImagePath))
195+
{
196+
throw new Exception("Image resizing failed during temporary file creation.");
197+
}
198+
199+
// 3. Update file metadata
200+
var fileInfo = new FileInfo(resizedImagePath);
201+
using (var image = await Image.LoadAsync(resizedImagePath))
202+
{
203+
file.ImageWidth = image.Width;
204+
file.ImageHeight = image.Height;
205+
}
206+
file.Size = (int)fileInfo.Length;
207+
208+
// 4. The file is now resized and metadata is updated, but we need to replace the original file
209+
// At this point, all handles to the original file should be closed.
210+
System.IO.File.Delete(originalFilePath);
211+
System.IO.File.Move(resizedImagePath, originalFilePath);
212+
213+
_files.UpdateFile(file);
214+
215+
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Image Resized Successfully {FileId}", request.FileId);
216+
return Ok(file);
217+
}
218+
else
219+
{
220+
_logger.Log(LogLevel.Error, this, LogFunction.Read, "File Not Found For Resizing {FileId}", request.FileId);
221+
return NotFound();
222+
}
223+
}
224+
catch (Exception ex)
225+
{
226+
// Clean up temporary file if it exists
227+
if (!string.IsNullOrEmpty(tempFilePath) && System.IO.File.Exists(tempFilePath))
228+
{
229+
System.IO.File.Delete(tempFilePath);
230+
}
231+
232+
_logger.Log(LogLevel.Error, this, LogFunction.Update, ex, "Error Resizing Image {FileId}", request.FileId);
233+
return StatusCode(500, "An error occurred while resizing the image.");
234+
}
235+
}
236+
160237
[HttpPost("upload")]
161238
public async Task<IActionResult> UploadFile([FromForm] string folder, [FromForm] IFormFile file)
162239
{
@@ -282,5 +359,13 @@ public class UpdateCompanyAttributesRequest
282359
public int ModuleId { get; set; }
283360
public List<int> AttributeIds { get; set; }
284361
}
362+
363+
public class ResizeRequest
364+
{
365+
public int FileId { get; set; }
366+
public int Width { get; set; }
367+
public int Height { get; set; }
368+
public int ModuleId { get; set; }
369+
}
285370
}
286371
}

Server/GIBS.Module.BusinessDirectory.Server.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,8 @@
3636
<Reference Include="Oqtane.Shared">
3737
<HintPath>..\..\oqtane.framework-6.1.2-Source\Oqtane.Server\bin\Debug\net9.0\Oqtane.Shared.dll</HintPath>
3838
</Reference>
39+
<Reference Include="SixLabors.ImageSharp">
40+
<HintPath>..\..\oqtane.framework-6.1.2-Source\Oqtane.Server\bin\Debug\net9.0\SixLabors.ImageSharp.dll</HintPath>
41+
</Reference>
3942
</ItemGroup>
4043
</Project>

Server/Services/BusinessCompanyService.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,5 +150,11 @@ public async Task UpdateCompanyAttributesAsync(int companyId, int moduleId, List
150150
{
151151
return await _businessCompanyRepository.GetCompanyAttributesAsync(companyId, moduleId);
152152
}
153+
154+
public Task<Oqtane.Models.File> ResizeImageAsync(int fileId, int width, int height, int moduleId)
155+
{
156+
// This is handled by the controller, so no implementation is needed here.
157+
throw new NotImplementedException();
158+
}
153159
}
154160
}

Shared/Interfaces/IBusinessCompanyService.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@ public interface IBusinessCompanyService
2626
Task UpdateCompanyAttributesAsync(int companyId, int moduleId, List<int> attributeIds);
2727

2828
Task<List<Models.BusinessCompany>> GetCompanyAttributesAsync(int companyId, int moduleId);
29+
Task<Oqtane.Models.File> ResizeImageAsync(int fileId, int width, int height, int moduleId);
2930
}
3031
}

0 commit comments

Comments
 (0)