using HyperBooru.Services; using HyperBooru.Util; using ImageMagick; using Microsoft.AspNetCore.Mvc; using MimeDetective; using System.Security.Cryptography; namespace HyperBooru.Controllers; [ApiController] [Route("/media")] public class MediaController : Controller { private IMediaService mediaService; private IConfigService config; private HBContext db; public MediaController( IMediaService mediaService, IConfigService config, HBContext db) { this.mediaService = mediaService; this.config = config; this.db = db; } [HttpGet("{mediaId}")] public IActionResult Fetch([FromRoute] Guid mediaId) { var media = db.Media.First(m => m.Guid == mediaId); if(media is null) return NotFound(); var fs = System.IO.File.OpenRead(mediaService.GetPath(media)); return new FileStreamResult(fs, media.MimeType); } [HttpGet("thumb/{mediaId}")] public IActionResult Thumbnail( [FromRoute] Guid mediaId, [FromQuery] int? w, [FromQuery] int? h) { var media = db.Media.First(m => m.Guid == mediaId); if(media is null) return NotFound(); if(media.MimeType.Split("/")[0] != "image") return BadRequest("Media object not an image"); using var image = new MagickImage(mediaService.GetPath(media)); if(w is null && h is null) return BadRequest("Both width and height cannot be null!"); if(w > image.Width || h > image.Height) return BadRequest("Requested thumbnail size is larger than original media"); int width = (int)(w is not null ? w : image.Width * h / image.Height); int height = (int)(h is not null ? h : image.Height * w / image.Width); var thumbPath = mediaService.GetPath(media, width, height); if(!System.IO.File.Exists(thumbPath)) { image.Resize(new MagickGeometry(width, height)); image.Write(thumbPath); } var fs = System.IO.File.OpenRead(thumbPath); return new FileStreamResult(fs, "image/jpeg"); } [HttpDelete("{mediaId}")] public void Delete([FromRoute] Guid mediaId) { mediaService.Delete(mediaId); } [HttpPost] public IActionResult Upload() { if(Request.Form.Files.Count == 0) return BadRequest("No files"); Media media = new(); foreach(var formFile in Request.Form.Files) { try { // Parse timestamps from headers DateTime? lastAccessTime = formFile.Headers["X-HyperBooru-LastAccessTime"] .ElementAtOrDefault(0)? .TryParseDateTimeUtc(); DateTime? lastWriteTime = formFile.Headers["X-HyperBooru-LastWriteTime"] .ElementAtOrDefault(0)? .TryParseDateTimeUtc(); DateTime? createTime = formFile.Headers["X-HyperBooru-CreateTime"] .ElementAtOrDefault(0)? .TryParseDateTimeUtc(); media = mediaService.Create( formFile.OpenReadStream(), formFile.FileName, formFile.Headers["X-HyperBooru-Checksum"] .ElementAtOrDefault(0), lastAccessTime, lastWriteTime, createTime); } catch(MediaCreateException e) { return BadRequest(e.Message); } } if(Request.Form.Files.Count == 1) return Redirect($"/ViewMedia?m={media.Guid}"); else return Redirect($"/Gallery"); } }