diff options
| author | Jake Mannens <jake@asger.xyz> | 2023-08-15 15:49:14 +1000 |
|---|---|---|
| committer | Jake Mannens <jake@asger.xyz> | 2023-08-15 15:49:14 +1000 |
| commit | 8e94a12be4a56447e78d68c37def772bef8cade4 (patch) | |
| tree | 0a12c64f8e34da45df8ac8e4c484c83385aedb45 /Controllers | |
| parent | 5b00f23b28e3a09a4120101a8be8802d009e5d84 (diff) | |
Convert Razor pages to Blazor
Diffstat (limited to 'Controllers')
| -rw-r--r-- | Controllers/MediaController.cs | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/Controllers/MediaController.cs b/Controllers/MediaController.cs new file mode 100644 index 0000000..3f36064 --- /dev/null +++ b/Controllers/MediaController.cs @@ -0,0 +1,170 @@ +using HyperBooru.Services; +using ImageMagick; +using Microsoft.AspNetCore.Mvc; +using MimeDetective; +using System.Security.Cryptography; + +namespace HyperBooru.Controllers; + +[ApiController] +[Route("/media")] +public class MediaController : Controller { + private IConfigService config; + private HBContext db; + + private ContentInspector inspector; + + public MediaController(IConfigService config, HBContext db) { + this.config = config; + this.db = db; + + ContentInspectorBuilder inspectorBuilder = new() { + Definitions = + MimeDetective.Definitions.Default.FileTypes.Images.All() + .Union(MimeDetective.Definitions.Default.FileTypes.Video.All()) + .ToList() + }; + + inspector = inspectorBuilder.Build(); + } + + [HttpGet("list")] + public IActionResult EnumerateMedia() => + Ok(db.Media.Select(m => m.ObjectId).ToArray()); + + [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(config.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(config.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 = config.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 IActionResult Delete([FromRoute] Guid mediaId) { + var media = db.Media.First(m => m.Guid == mediaId); + if(media is null) + return NotFound(); + + System.IO.File.Delete(config.GetPath(media)); + + db.Media.Remove(media); + db.SaveChanges(); + return Ok(); + } + + [HttpPost] + public IActionResult Upload( + [FromForm] string? checksum, + [FromForm] DateTime? lastAccessTime, + [FromForm] DateTime? lastWriteTime, + [FromForm] DateTime? createTime) { + + using var transaction = db.Database.BeginTransaction(); + + var formFile = Request.Form.Files[0]; + if(formFile.Length < 1) + return BadRequest("Empty file"); + + var formStream = formFile.OpenReadStream(); + + // Calculate the checksum using the in-memory file contents + var hash = BitConverter + .ToString(MD5.Create().ComputeHash(formStream)) + .Replace("-", "") + .ToLower(); + + if(checksum is not null && hash != checksum.ToLower()) + return BadRequest("Checksum does not match"); + + var fileRecord = new UploadedFile() { + Filename = formFile.FileName, + OriginalChecksum = hash, + UploadTime = DateTime.Now, + LastAccessTime = lastAccessTime, + LastWriteTime = lastWriteTime, + CreateTime = createTime + }; + + formStream.Seek(0, SeekOrigin.Begin); + var defs = inspector.Inspect(formStream); + + var mime = defs.ByMimeType().FirstOrDefault()?.MimeType; + if(mime is null) + return BadRequest("Unsupported file type"); + + var media = db.Media + .FirstOrDefault(m => m.Checksum == hash); + + if(media is null) { + var ingestTagDef = db.TagDefinitions + .First(td => td.Source == TagSource.Internal && td.Name == "ingest"); + + media = new() { + Checksum = hash, + MimeType = mime, + UploadedFiles = new() { + fileRecord + }, + Tags = new() { + new() { TagDefinition = ingestTagDef } + } + }; + + using var newFile = System.IO.File.Create(config.GetPath(media)); + + formStream.Seek(0, SeekOrigin.Begin); + formStream.CopyTo(newFile); + newFile.Flush(); + + db.Media.Add(media); + } else { + media.UploadedFiles.Add(fileRecord); + db.Update(media); + } + + db.SaveChanges(); + transaction.Commit(); + + return Ok(media.Guid); + } +}
\ No newline at end of file |
