mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-07-09 03:04:19 -04:00
Implemented the ability to extract an archive image to a cache directory.
This commit is contained in:
parent
14ad2a3dd5
commit
7ab7e8acc4
3
.gitignore
vendored
3
.gitignore
vendored
@ -447,4 +447,5 @@ appsettings.json
|
||||
/API/kavita.db-shm
|
||||
/API/kavita.db-wal
|
||||
/API/Hangfire.db
|
||||
/API/Hangfire-log.db
|
||||
/API/Hangfire-log.db
|
||||
cache/
|
46
API/Controllers/ReaderController.cs
Normal file
46
API/Controllers/ReaderController.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using API.Entities;
|
||||
using API.Interfaces;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace API.Controllers
|
||||
{
|
||||
public class ReaderController : BaseApiController
|
||||
{
|
||||
private readonly ISeriesRepository _seriesRepository;
|
||||
private readonly IDirectoryService _directoryService;
|
||||
|
||||
public ReaderController(ISeriesRepository seriesRepository, IDirectoryService directoryService)
|
||||
{
|
||||
_seriesRepository = seriesRepository;
|
||||
_directoryService = directoryService;
|
||||
}
|
||||
|
||||
[HttpGet("info")]
|
||||
public async Task<ActionResult<int>> GetInformation(int volumeId)
|
||||
{
|
||||
Volume volume = await _seriesRepository.GetVolumeAsync(volumeId);
|
||||
|
||||
// Assume we always get first Manga File
|
||||
if (volume == null || !volume.Files.Any())
|
||||
{
|
||||
return BadRequest("There are no files in the volume to read.");
|
||||
}
|
||||
|
||||
var filepath = volume.Files.ElementAt(0).FilePath;
|
||||
|
||||
var extractPath = _directoryService.ExtractArchive(filepath, volumeId);
|
||||
if (string.IsNullOrEmpty(extractPath))
|
||||
{
|
||||
return BadRequest("There file is no longer there or has no images. Please rescan.");
|
||||
}
|
||||
|
||||
return Ok(_directoryService.ListFiles(extractPath).Count());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -76,5 +76,12 @@ namespace API.Data
|
||||
return await _context.Series.Where(x => x.Id == seriesId)
|
||||
.ProjectTo<SeriesDto>(_mapper.ConfigurationProvider).SingleAsync();
|
||||
}
|
||||
|
||||
public async Task<Volume> GetVolumeAsync(int volumeId)
|
||||
{
|
||||
return await _context.Volume
|
||||
.Include(vol => vol.Files)
|
||||
.SingleOrDefaultAsync(vol => vol.Id == volumeId);
|
||||
}
|
||||
}
|
||||
}
|
@ -16,6 +16,8 @@ namespace API.Entities
|
||||
public uint RowVersion { get; set; }
|
||||
|
||||
public ICollection<AppUserRole> UserRoles { get; set; }
|
||||
|
||||
//public ICollection<SeriesProgress> SeriesProgresses { get; set; }
|
||||
|
||||
public void OnSavingChanges()
|
||||
{
|
||||
|
@ -4,8 +4,38 @@ namespace API.Interfaces
|
||||
{
|
||||
public interface IDirectoryService
|
||||
{
|
||||
/// <summary>
|
||||
/// Lists out top-level folders for a given directory. Filters out System and Hidden folders.
|
||||
/// </summary>
|
||||
/// <param name="rootPath">Absolute path of directory to scan.</param>
|
||||
/// <returns>List of folder names</returns>
|
||||
IEnumerable<string> ListDirectory(string rootPath);
|
||||
|
||||
/// <summary>
|
||||
/// Lists out top-level files for a given directory.
|
||||
/// TODO: Implement ability to provide a filter for file types
|
||||
/// </summary>
|
||||
/// <param name="rootPath">Absolute path </param>
|
||||
/// <returns>List of folder names</returns>
|
||||
IEnumerable<string> ListFiles(string rootPath);
|
||||
|
||||
/// <summary>
|
||||
/// Given a library id, scans folders for said library. Parses files and generates DB updates. Will overwrite
|
||||
/// cover images if forceUpdate is true.
|
||||
/// </summary>
|
||||
/// <param name="libraryId">Library to scan against</param>
|
||||
/// <param name="forceUpdate">Force overwriting for cover images</param>
|
||||
void ScanLibrary(int libraryId, bool forceUpdate);
|
||||
|
||||
/// <summary>
|
||||
/// Extracts an archive to a temp cache directory. Returns path to new directory. If temp cache directory already exists,
|
||||
/// will return that without performing an extraction. Returns empty string if there are any invalidations which would
|
||||
/// prevent operations to perform correctly (missing archivePath file, empty archive, etc).
|
||||
/// </summary>
|
||||
/// <param name="archivePath">A valid file to an archive file.</param>
|
||||
/// <param name="volumeId">Id of volume being extracted.</param>
|
||||
/// <returns></returns>
|
||||
string ExtractArchive(string archivePath, int volumeId);
|
||||
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@ namespace API.Interfaces
|
||||
Task<IEnumerable<VolumeDto>> GetVolumesDtoAsync(int seriesId);
|
||||
IEnumerable<Volume> GetVolumes(int seriesId);
|
||||
Task<SeriesDto> GetSeriesDtoByIdAsync(int seriesId);
|
||||
|
||||
|
||||
Task<Volume> GetVolumeAsync(int volumeId);
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
@ -51,11 +52,6 @@ namespace API.Services
|
||||
reSearchPattern.IsMatch(Path.GetExtension(file)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lists out top-level folders for a given directory. Filters out System and Hidden folders.
|
||||
/// </summary>
|
||||
/// <param name="rootPath">Absolute path </param>
|
||||
/// <returns>List of folder names</returns>
|
||||
public IEnumerable<string> ListDirectory(string rootPath)
|
||||
{
|
||||
if (!Directory.Exists(rootPath)) return ImmutableList<string>.Empty;
|
||||
@ -69,6 +65,12 @@ namespace API.Services
|
||||
return dirs;
|
||||
}
|
||||
|
||||
public IEnumerable<string> ListFiles(string rootPath)
|
||||
{
|
||||
if (!Directory.Exists(rootPath)) return ImmutableList<string>.Empty;
|
||||
return Directory.GetFiles(rootPath);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Processes files found during a library scan. Generates a collection of series->volume->files for DB processing later.
|
||||
@ -153,7 +155,7 @@ namespace API.Services
|
||||
{
|
||||
new MangaFile()
|
||||
{
|
||||
FilePath = info.File
|
||||
FilePath = info.FullFilePath
|
||||
}
|
||||
};
|
||||
|
||||
@ -189,6 +191,7 @@ namespace API.Services
|
||||
|
||||
public void ScanLibrary(int libraryId, bool forceUpdate)
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
var library = Task.Run(() => _libraryRepository.GetLibraryForIdAsync(libraryId)).Result;
|
||||
_scannedSeries = new ConcurrentDictionary<string, ConcurrentBag<ParserInfo>>();
|
||||
_logger.LogInformation($"Beginning scan on {library.Name}");
|
||||
@ -239,6 +242,35 @@ namespace API.Services
|
||||
}
|
||||
|
||||
_scannedSeries = null;
|
||||
Console.WriteLine("Processed {0} files in {1} milliseconds", library.Name, sw.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public string ExtractArchive(string archivePath, int volumeId)
|
||||
{
|
||||
if (!File.Exists(archivePath) || !Parser.Parser.IsArchive(archivePath))
|
||||
{
|
||||
_logger.LogError($"Archive {archivePath} could not be found.");
|
||||
return "";
|
||||
}
|
||||
|
||||
var extractPath = Path.Join(Directory.GetCurrentDirectory(), $"../cache/{volumeId}/");
|
||||
|
||||
if (Directory.Exists(extractPath))
|
||||
{
|
||||
_logger.LogInformation($"Archive {archivePath} has already been extracted. Returning existing folder.");
|
||||
return extractPath;
|
||||
}
|
||||
|
||||
using ZipArchive archive = ZipFile.OpenRead(archivePath);
|
||||
|
||||
if (archive.Entries.Count <= 0) return "";
|
||||
|
||||
archive.ExtractToDirectory(extractPath);
|
||||
_logger.LogInformation($"Extracting archive to {extractPath}");
|
||||
|
||||
return extractPath;
|
||||
}
|
||||
|
||||
private static void TraverseTreeParallelForEach(string root, Action<string> action)
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 1.1 MiB |
Loading…
x
Reference in New Issue
Block a user