From 7bf04dcdacd1f53ec473b47c222adc779662a938 Mon Sep 17 00:00:00 2001 From: Joseph Milazzo Date: Fri, 8 Jan 2021 15:17:39 -0600 Subject: [PATCH] Implemented the ability to send images to frontend with some contextual information. --- API/Controllers/ReaderController.cs | 20 +++++++++++++++++-- API/DTOs/ImageDto.cs | 13 ++++++++++++ API/Data/Seed.cs | 6 +++++- API/Entities/MangaFile.cs | 1 + API/Interfaces/IDirectoryService.cs | 13 +++++++++++- API/Services/DirectoryService.cs | 31 +++++++++++++++++++++++------ 6 files changed, 74 insertions(+), 10 deletions(-) create mode 100644 API/DTOs/ImageDto.cs diff --git a/API/Controllers/ReaderController.cs b/API/Controllers/ReaderController.cs index 3251cce69..e1589e89c 100644 --- a/API/Controllers/ReaderController.cs +++ b/API/Controllers/ReaderController.cs @@ -1,7 +1,9 @@ using System; +using System.IO; using System.IO.Compression; using System.Linq; using System.Threading.Tasks; +using API.DTOs; using API.Entities; using API.Interfaces; using Microsoft.AspNetCore.Mvc; @@ -38,9 +40,23 @@ namespace API.Controllers return BadRequest("There file is no longer there or has no images. Please rescan."); } + // NOTE: I'm starting to think this should actually cache the information about Volume/Manga file in the DB. + // It will be updated each time this is called which is on open of a manga. return Ok(_directoryService.ListFiles(extractPath).Count()); } - - + + [HttpGet("image")] + public async Task> GetImage(int volumeId, int page) + { + // Temp let's iterate the directory each call to get next image + var files = _directoryService.ListFiles(_directoryService.GetExtractPath(volumeId)); + var path = files.ElementAt(page); + var file = await _directoryService.ReadImageAsync(path); + file.Page = page; + + return Ok(file); + + //return File(await _directoryService.ReadImageAsync(path), "image/jpg", filename); + } } } \ No newline at end of file diff --git a/API/DTOs/ImageDto.cs b/API/DTOs/ImageDto.cs new file mode 100644 index 000000000..473f2c110 --- /dev/null +++ b/API/DTOs/ImageDto.cs @@ -0,0 +1,13 @@ +namespace API.DTOs +{ + public class ImageDto + { + public int Page { get; set; } + public string Filename { get; init; } + public string FullPath { get; init; } + public int Width { get; init; } + public int Height { get; init; } + public string Format { get; init; } + public byte[] Content { get; init; } + } +} \ No newline at end of file diff --git a/API/Data/Seed.cs b/API/Data/Seed.cs index 8d7f619c3..9729d0a82 100644 --- a/API/Data/Seed.cs +++ b/API/Data/Seed.cs @@ -18,7 +18,11 @@ namespace API.Data foreach (var role in roles) { - await roleManager.CreateAsync(role); + var exists = await roleManager.RoleExistsAsync(role.Name); + if (!exists) + { + await roleManager.CreateAsync(role); + } } } } diff --git a/API/Entities/MangaFile.cs b/API/Entities/MangaFile.cs index 06e132193..121265d3d 100644 --- a/API/Entities/MangaFile.cs +++ b/API/Entities/MangaFile.cs @@ -5,6 +5,7 @@ namespace API.Entities { public int Id { get; set; } public string FilePath { get; set; } + // Should I just store information related to FilePath here? Reset it on anytime FilePath changes? // Relationship Mapping public Volume Volume { get; set; } diff --git a/API/Interfaces/IDirectoryService.cs b/API/Interfaces/IDirectoryService.cs index c938e9685..664f7a631 100644 --- a/API/Interfaces/IDirectoryService.cs +++ b/API/Interfaces/IDirectoryService.cs @@ -1,7 +1,10 @@ using System.Collections.Generic; +using System.Threading.Tasks; +using API.DTOs; namespace API.Interfaces { + // TODO: Refactor this into IDiskService to encapsulate all disk based IO public interface IDirectoryService { /// @@ -36,6 +39,14 @@ namespace API.Interfaces /// Id of volume being extracted. /// string ExtractArchive(string archivePath, int volumeId); - + + /// + /// Returns the path a volume would be extracted to. + /// + /// + /// + string GetExtractPath(int volumeId); + + Task ReadImageAsync(string imagePath); } } \ No newline at end of file diff --git a/API/Services/DirectoryService.cs b/API/Services/DirectoryService.cs index 379d07467..1175c7169 100644 --- a/API/Services/DirectoryService.cs +++ b/API/Services/DirectoryService.cs @@ -9,12 +9,13 @@ using System.Linq; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using API.DTOs; using API.Entities; using API.Interfaces; using API.IO; using API.Parser; -using Hangfire; using Microsoft.Extensions.Logging; +using NetVips; namespace API.Services { @@ -244,8 +245,11 @@ namespace API.Services _scannedSeries = null; Console.WriteLine("Processed {0} files in {1} milliseconds", library.Name, sw.ElapsedMilliseconds); } - - + + public string GetExtractPath(int volumeId) + { + return Path.Join(Directory.GetCurrentDirectory(), $"../cache/{volumeId}/"); + } public string ExtractArchive(string archivePath, int volumeId) { @@ -255,7 +259,7 @@ namespace API.Services return ""; } - var extractPath = Path.Join(Directory.GetCurrentDirectory(), $"../cache/{volumeId}/"); + var extractPath = GetExtractPath(volumeId); if (Directory.Exists(extractPath)) { @@ -273,11 +277,26 @@ namespace API.Services return extractPath; } + public async Task ReadImageAsync(string imagePath) + { + using var image = Image.NewFromFile(imagePath); + + return new ImageDto + { + Content = await File.ReadAllBytesAsync(imagePath), + Filename = Path.GetFileNameWithoutExtension(imagePath), + FullPath = Path.GetFullPath(imagePath), + Width = image.Width, + Height = image.Height, + Format = image.Format + }; + } + private static void TraverseTreeParallelForEach(string root, Action action) { //Count of files traversed and timer for diagnostic output int fileCount = 0; - var sw = Stopwatch.StartNew(); + //var sw = Stopwatch.StartNew(); // Determine whether to parallelize file processing on each folder based on processor count. int procCount = Environment.ProcessorCount; @@ -366,7 +385,7 @@ namespace API.Services } // For diagnostic purposes. - Console.WriteLine("Processed {0} files in {1} milliseconds", fileCount, sw.ElapsedMilliseconds); + //Console.WriteLine("Processed {0} files in {1} milliseconds", fileCount, sw.ElapsedMilliseconds); } }