diff --git a/Wave/Controllers/ImageController.cs b/Wave/Controllers/ImageController.cs index d91d987..5b72f62 100644 --- a/Wave/Controllers/ImageController.cs +++ b/Wave/Controllers/ImageController.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; +using System.ComponentModel.DataAnnotations; using Wave.Services; namespace Wave.Controllers; @@ -7,14 +8,15 @@ namespace Wave.Controllers; [ApiController] [Route("/images")] public class ImageController(ImageService imageService) : ControllerBase { - private ImageService ImageService { get; } = imageService; + private ImageService ImageService { get; } = imageService; - [HttpGet] - [Route("{imageId:guid}")] - public IActionResult Get(Guid imageId) { - string? path = ImageService.GetPath(imageId); + [HttpGet] + [Route("{imageId:guid}")] + public async Task Get(Guid imageId, [FromQuery, Range(16, 800)] int size = 800) { + string? path = ImageService.GetPath(imageId); - if (path is null) return NotFound(); - return File(System.IO.File.OpenRead(path), ImageService.ImageMimeType); - } + if (path is null) return NotFound(); + if (size < 800) return File(await ImageService.GetResized(path, size), ImageService.ImageMimeType); + return File(System.IO.File.OpenRead(path), ImageService.ImageMimeType); + } } \ No newline at end of file diff --git a/Wave/Controllers/UserController.cs b/Wave/Controllers/UserController.cs index 1c9a986..db1410b 100644 --- a/Wave/Controllers/UserController.cs +++ b/Wave/Controllers/UserController.cs @@ -1,5 +1,4 @@ using System.ComponentModel.DataAnnotations; -using ImageMagick; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.OutputCaching; @@ -31,15 +30,7 @@ public class UserController(ImageService imageService, IDbContextFactory logger) { - private ILogger Logger { get; } = logger; - private const string BasePath = "./files/images"; - private const string ImageExtension = ".jpg"; - public string ImageMimeType => "image/jpg"; + private ILogger Logger { get; } = logger; + private const string BasePath = "./files/images"; + private const string ImageExtension = ".jpg"; + public string ImageMimeType => "image/jpg"; - public string? GetPath(Guid imageId) { - string path = Path.Combine(BasePath, imageId + ImageExtension); - return File.Exists(path) ? path : null; - } + public string? GetPath(Guid imageId) { + string path = Path.Combine(BasePath, imageId + ImageExtension); + return File.Exists(path) ? path : null; + } - public async ValueTask StoreImageAsync(string temporaryPath, int size = 800, CancellationToken cancellation = default) { - if (File.Exists(temporaryPath) is not true) return null; + public async Task GetResized(string path, int size) { + var image = new MagickImage(path); + image.Resize(new MagickGeometry(size)); + using var memory = new MemoryStream(); + await image.WriteAsync(memory); + return memory.ToArray(); + } - try { - if (File.Exists(BasePath) is not true) Directory.CreateDirectory(BasePath); + public async ValueTask StoreImageAsync(string temporaryPath, int size = 800, + CancellationToken cancellation = default) { + if (File.Exists(temporaryPath) is not true) return null; - var image = new MagickImage(); - await image.ReadAsync(temporaryPath, cancellation); + try { + if (File.Exists(BasePath) is not true) Directory.CreateDirectory(BasePath); - // Jpeg with 90% compression should look decent - image.Resize(new MagickGeometry(size)); // this preserves aspect ratio - image.Format = MagickFormat.Jpeg; - image.Quality = 90; + var image = new MagickImage(); + await image.ReadAsync(temporaryPath, cancellation); - if (image.GetExifProfile() is not null) { - image.RemoveProfile(image.GetExifProfile()); - } + // Jpeg with 90% compression should look decent + image.Resize(new MagickGeometry(size)); // this preserves aspect ratio + image.Format = MagickFormat.Jpeg; + image.Quality = 90; - // Overwrite exif for privacy reasons - var exif = new ExifProfile { - Parts = ExifParts.None - }; - exif.CreateThumbnail(); - image.SetProfile(exif); - - var guid = Guid.NewGuid(); - string path = Path.Combine(BasePath, guid + ImageExtension); - await image.WriteAsync(path, cancellation); - return guid; - } catch (Exception ex) { - Logger.LogInformation(ex, "Failed to process uploaded image."); - return null; - } - } + if (image.GetExifProfile() is { } exifProfile) image.RemoveProfile(exifProfile); - public void Delete(Guid imageId) { - string path = Path.Combine(BasePath, imageId + ImageExtension); - File.Delete(path); - } + // Overwrite exif for privacy reasons + var exif = new ExifProfile { + Parts = ExifParts.None + }; + exif.CreateThumbnail(); + image.SetProfile(exif); + + var guid = Guid.NewGuid(); + string path = Path.Combine(BasePath, guid + ImageExtension); + await image.WriteAsync(path, cancellation); + return guid; + } catch (Exception ex) { + Logger.LogInformation(ex, "Failed to process uploaded image."); + return null; + } + } + + public void Delete(Guid imageId) { + string path = Path.Combine(BasePath, imageId + ImageExtension); + File.Delete(path); + } } \ No newline at end of file