summaryrefslogtreecommitdiff
path: root/Controllers/MediaController.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Controllers/MediaController.cs')
-rw-r--r--Controllers/MediaController.cs145
1 files changed, 145 insertions, 0 deletions
diff --git a/Controllers/MediaController.cs b/Controllers/MediaController.cs
new file mode 100644
index 0000000..248765a
--- /dev/null
+++ b/Controllers/MediaController.cs
@@ -0,0 +1,145 @@
+using HyperBooru.ApiModels;
+using HyperBooru.Services;
+using HyperBooru.Util;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+
+namespace HyperBooru.Controllers;
+
+[ApiController]
+[Authorize]
+[Route("/media")]
+public class MediaController : Controller {
+ private IHttpContextAccessor httpContextAccessor;
+ private IMediaService mediaService;
+ private IConfigService config;
+ private HBContext db;
+
+ private readonly string[] FormatPriority = [
+ "image/webp",
+ "image/png"
+ ];
+
+ public MediaController(
+ IHttpContextAccessor httpContextAccessor,
+ IMediaService mediaService,
+ IConfigService config,
+ HBContext db) {
+
+ this.httpContextAccessor = httpContextAccessor;
+ this.mediaService = mediaService;
+ this.config = config;
+ this.db = db;
+ }
+
+ [HttpGet("{mediaId}")]
+ public IActionResult Fetch([FromRoute] Guid mediaId) {
+ var media = db.Media
+ .Include(m => m.CurrentUploadedFile)
+ .First(m => m.Guid == mediaId);
+ if(media is null)
+ throw new ObjectNotFoundException([ mediaId ]);
+
+ // Check if the requested media item is a HEIC image and if it is, convert it
+ // otherwise, return the original file content, unaltered
+ if(media.CurrentUploadedFile!.MimeType == "image/heic") {
+ // If the media needs to be converted, check the HTTP request for allowed
+ // media formats, and convert to the best available format or WebP otherwise
+ var allowedTypes = httpContextAccessor
+ .HttpContext?
+ .Request
+ .GetTypedHeaders().Accept.Select(h => h.MediaType.ToString()) ?? Array.Empty<string>();
+
+ var format = FormatPriority.FirstOrDefault(f => allowedTypes.Contains(f)) ?? "image/webp";
+
+ var fs = mediaService.GetConverted(media, format);
+
+ return new FileStreamResult(fs, format);
+ } else {
+ var fs = System.IO.File.OpenRead(mediaService.GetPath(media));
+ return new FileStreamResult(fs, media.CurrentUploadedFile!.MimeType);
+ }
+ }
+
+ [HttpGet("thumb/{mediaId}")]
+ public IActionResult Thumbnail(
+ [FromRoute] Guid mediaId,
+ [FromQuery(Name = "w")] int? width,
+ [FromQuery(Name = "h")] int? height) {
+
+ var thumb = mediaService.GetThumbnail(mediaId, width, height);
+ return new FileStreamResult(thumb, "image/jpeg");
+ }
+
+ [HttpDelete("{mediaId}")]
+ public void Delete([FromRoute] Guid mediaId) {
+ mediaService.Delete(mediaId);
+ }
+
+ [HttpPost]
+ public IActionResult Upload() {
+ if(Request.Form.Files.Count == 0)
+ throw new ApiModels.ArgumentException("No files");
+
+ Media media = new();
+
+ foreach(var formFile in Request.Form.Files) {
+ // 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();
+
+ // Parse original path from headers
+ string? path =
+ formFile.Headers["X-HyperBooru-Path"]
+ .ElementAtOrDefault(0);
+
+ object? pathType = null;
+ string? pathTypeString =
+ formFile.Headers["X-HyperBooru-PathType"]
+ .ElementAtOrDefault(0);
+ Enum.TryParse(typeof(PathType), pathTypeString, true, out pathType);
+
+ // Parse tag IDs from headers
+ Guid[]? tagIds = formFile.Headers["X-HyperBooru-Tags"]
+ .ElementAtOrDefault(0)?
+ .Split(',')
+ .Select(t => Guid.Parse(t))
+ .ToArray();
+
+ media = mediaService.Create(
+ formFile.OpenReadStream(),
+ formFile.FileName,
+ formFile.Headers["X-HyperBooru-Checksum"]
+ .ElementAtOrDefault(0),
+ lastAccessTime,
+ lastWriteTime,
+ createTime,
+ path,
+ (PathType?) pathType,
+ tagIds);
+
+ // Return the GUID of the new media object if requested
+ bool returnMetadataParsed = bool.TryParse(
+ formFile.Headers["X-HyperBooru-ReturnMediaId"], out var returnMetadata);
+
+ if(returnMetadataParsed && returnMetadata)
+ return Content(media.Guid.ToString());
+ }
+
+ if(Request.Form.Files.Count == 1)
+ return Redirect($"/ViewMedia?m={media.Guid}");
+ else
+ return Redirect($"/Gallery");
+ }
+} \ No newline at end of file