Cleanup and tests fixup

This commit is contained in:
Joseph Milazzo 2021-03-23 14:37:47 -05:00
parent 154b30c3fd
commit 6ebf5d6254
6 changed files with 88 additions and 188 deletions

View File

@ -1,6 +1,7 @@
using System; using System.Diagnostics;
using System.Diagnostics;
using System.IO; using System.IO;
using System.IO.Compression;
using API.Archive;
using API.Interfaces.Services; using API.Interfaces.Services;
using API.Services; using API.Services;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -22,18 +23,18 @@ namespace API.Tests.Services
_archiveService = new ArchiveService(_logger); _archiveService = new ArchiveService(_logger);
} }
// [Theory] [Theory]
// [InlineData("flat file.zip", false)] [InlineData("flat file.zip", false)]
// [InlineData("file in folder in folder.zip", true)] [InlineData("file in folder in folder.zip", true)]
// [InlineData("file in folder.zip", true)] [InlineData("file in folder.zip", true)]
// [InlineData("file in folder_alt.zip", true)] [InlineData("file in folder_alt.zip", true)]
// public void ArchiveNeedsFlatteningTest(string archivePath, bool expected) public void ArchiveNeedsFlatteningTest(string archivePath, bool expected)
// { {
// var testDirectory = Path.Join(Directory.GetCurrentDirectory(), "../../../Services/Test Data/ArchiveService/Archives"); var testDirectory = Path.Join(Directory.GetCurrentDirectory(), "../../../Services/Test Data/ArchiveService/Archives");
// var file = Path.Join(testDirectory, archivePath); var file = Path.Join(testDirectory, archivePath);
// using ZipArchive archive = ZipFile.OpenRead(file); using ZipArchive archive = ZipFile.OpenRead(file);
// Assert.Equal(expected, _archiveService.ArchiveNeedsFlattening(archive)); Assert.Equal(expected, _archiveService.ArchiveNeedsFlattening(archive));
// } }
[Theory] [Theory]
[InlineData("non existent file.zip", false)] [InlineData("non existent file.zip", false)]
@ -68,19 +69,19 @@ namespace API.Tests.Services
[Theory] [Theory]
[InlineData("non existent file.zip", false)] [InlineData("non existent file.zip", ArchiveLibrary.NotSupported)]
[InlineData("winrar.rar", true)] [InlineData("winrar.rar", ArchiveLibrary.SharpCompress)]
//[InlineData("empty.zip", false)] [InlineData("empty.zip", ArchiveLibrary.Default)]
[InlineData("flat file.zip", true)] [InlineData("flat file.zip", ArchiveLibrary.Default)]
[InlineData("file in folder in folder.zip", true)] [InlineData("file in folder in folder.zip", ArchiveLibrary.Default)]
[InlineData("file in folder.zip", true)] [InlineData("file in folder.zip", ArchiveLibrary.Default)]
[InlineData("file in folder_alt.zip", true)] [InlineData("file in folder_alt.zip", ArchiveLibrary.Default)]
public void CanOpenArchive(string archivePath, bool expected) public void CanOpenArchive(string archivePath, ArchiveLibrary expected)
{ {
var sw = Stopwatch.StartNew(); var sw = Stopwatch.StartNew();
var testDirectory = Path.Join(Directory.GetCurrentDirectory(), "../../../Services/Test Data/ArchiveService/Archives"); var testDirectory = Path.Join(Directory.GetCurrentDirectory(), "../../../Services/Test Data/ArchiveService/Archives");
Assert.Equal(expected, _archiveService.IsValidArchive(Path.Join(testDirectory, archivePath))); Assert.Equal(expected, _archiveService.CanOpen(Path.Join(testDirectory, archivePath)));
_testOutputHelper.WriteLine($"Processed Original in {sw.ElapsedMilliseconds} ms"); _testOutputHelper.WriteLine($"Processed Original in {sw.ElapsedMilliseconds} ms");
} }
@ -98,7 +99,8 @@ namespace API.Tests.Services
var testDirectory = Path.Join(Directory.GetCurrentDirectory(), "../../../Services/Test Data/ArchiveService/Archives"); var testDirectory = Path.Join(Directory.GetCurrentDirectory(), "../../../Services/Test Data/ArchiveService/Archives");
var extractDirectory = Path.Join(Directory.GetCurrentDirectory(), "../../../Services/Test Data/ArchiveService/Archives/Extraction"); var extractDirectory = Path.Join(Directory.GetCurrentDirectory(), "../../../Services/Test Data/ArchiveService/Archives/Extraction");
DirectoryService.ClearDirectory(extractDirectory);
DirectoryService.ClearAndDeleteDirectory(extractDirectory);
Stopwatch sw = Stopwatch.StartNew(); Stopwatch sw = Stopwatch.StartNew();
_archiveService.ExtractArchive(Path.Join(testDirectory, archivePath), extractDirectory); _archiveService.ExtractArchive(Path.Join(testDirectory, archivePath), extractDirectory);

View File

@ -1,42 +0,0 @@
using System;
using System.IO;
using System.IO.Compression;
using SharpCompress.Archives;
namespace API.Archive
{
public static class Archive
{
/// <summary>
/// Checks if a File can be opened. Requires up to 2 opens of the filestream.
/// </summary>
/// <param name="archivePath"></param>
/// <returns></returns>
public static ArchiveLibrary CanOpen(string archivePath)
{
// TODO: Should I introduce something for NotFound?
if (!File.Exists(archivePath) || !Parser.Parser.IsArchive(archivePath)) return ArchiveLibrary.NotSupported;
try
{
using var a2 = ZipFile.OpenRead(archivePath);
return ArchiveLibrary.Default;
}
catch (Exception)
{
try
{
using var a1 = ArchiveFactory.Open(archivePath);
return ArchiveLibrary.SharpCompress;
}
catch (Exception)
{
return ArchiveLibrary.NotSupported;
}
}
}
}
}

View File

@ -1,10 +0,0 @@
namespace API.Archive
{
public class ArchiveMetadata
{
public byte[] CoverImage { get; set; }
public string Summary { get; set; }
public int Pages { get; set; }
//public string Format { get; set; }
}
}

View File

@ -1,4 +1,5 @@
using API.Archive; using System.IO.Compression;
using API.Archive;
namespace API.Interfaces.Services namespace API.Interfaces.Services
{ {
@ -9,6 +10,7 @@ namespace API.Interfaces.Services
byte[] GetCoverImage(string filepath, bool createThumbnail = false); byte[] GetCoverImage(string filepath, bool createThumbnail = false);
bool IsValidArchive(string archivePath); bool IsValidArchive(string archivePath);
string GetSummaryInfo(string archivePath); string GetSummaryInfo(string archivePath);
ArchiveMetadata GetArchiveData(string archivePath, bool createThumbnail); ArchiveLibrary CanOpen(string archivePath);
bool ArchiveNeedsFlattening(ZipArchive archive);
} }
} }

View File

@ -1,5 +1,4 @@
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
@ -12,12 +11,7 @@ using API.Interfaces.Services;
using API.Services.Tasks; using API.Services.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using SharpCompress.Archives; using SharpCompress.Archives;
using SharpCompress.Archives.GZip;
using SharpCompress.Archives.Rar;
using SharpCompress.Archives.SevenZip;
using SharpCompress.Archives.Tar;
using SharpCompress.Common; using SharpCompress.Common;
using SharpCompress.Readers;
using Image = NetVips.Image; using Image = NetVips.Image;
namespace API.Services namespace API.Services
@ -35,6 +29,35 @@ namespace API.Services
_logger = logger; _logger = logger;
} }
/// <summary>
/// Checks if a File can be opened. Requires up to 2 opens of the filestream.
/// </summary>
/// <param name="archivePath"></param>
/// <returns></returns>
public ArchiveLibrary CanOpen(string archivePath)
{
if (!File.Exists(archivePath) || !Parser.Parser.IsArchive(archivePath)) return ArchiveLibrary.NotSupported;
try
{
using var a2 = ZipFile.OpenRead(archivePath);
return ArchiveLibrary.Default;
}
catch (Exception)
{
try
{
using var a1 = ArchiveFactory.Open(archivePath);
return ArchiveLibrary.SharpCompress;
}
catch (Exception)
{
return ArchiveLibrary.NotSupported;
}
}
}
public int GetNumberOfPagesFromArchive(string archivePath) public int GetNumberOfPagesFromArchive(string archivePath)
{ {
if (!IsValidArchive(archivePath)) if (!IsValidArchive(archivePath))
@ -48,7 +71,7 @@ namespace API.Services
try try
{ {
var libraryHandler = Archive.Archive.CanOpen(archivePath); var libraryHandler = CanOpen(archivePath);
switch (libraryHandler) switch (libraryHandler)
{ {
case ArchiveLibrary.Default: case ArchiveLibrary.Default:
@ -70,85 +93,14 @@ namespace API.Services
_logger.LogError("[GetNumberOfPagesFromArchive] There was an exception when reading archive stream: {ArchivePath}. Defaulting to 0 pages", archivePath); _logger.LogError("[GetNumberOfPagesFromArchive] There was an exception when reading archive stream: {ArchivePath}. Defaulting to 0 pages", archivePath);
return 0; return 0;
} }
// using Stream stream = File.OpenRead(archivePath);
// using (var reader = ReaderFactory.Open(stream))
// {
// try
// {
// _logger.LogDebug("{ArchivePath}'s Type: {ArchiveType}", archivePath, reader.ArchiveType);
// }
// catch (InvalidOperationException ex)
// {
// _logger.LogError(ex, "Could not parse the archive. Please validate it is not corrupted, {ArchivePath}", archivePath);
// return 0;
// }
//
// while (reader.MoveToNextEntry())
// {
// if (!reader.Entry.IsDirectory && Parser.Parser.IsImage(reader.Entry.Key))
// {
// count++;
// }
// }
// }
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "[GetNumberOfPagesFromArchive] There was an exception when reading archive stream: {ArchivePath}. Defaulting to 0 pages", archivePath); _logger.LogError(ex, "[GetNumberOfPagesFromArchive] There was an exception when reading archive stream: {ArchivePath}. Defaulting to 0 pages", archivePath);
return 0; return 0;
} }
try
{
using var archive = ArchiveFactory.Open(archivePath);
return archive.Entries.Where(entry => !entry.IsDirectory && Parser.Parser.IsImage(entry.Key)).Count();
// using Stream stream = File.OpenRead(archivePath);
// using (var reader = ReaderFactory.Open(stream))
// {
// try
// {
// _logger.LogDebug("{ArchivePath}'s Type: {ArchiveType}", archivePath, reader.ArchiveType);
// }
// catch (InvalidOperationException ex)
// {
// _logger.LogError(ex, "Could not parse the archive. Please validate it is not corrupted, {ArchivePath}", archivePath);
// return 0;
// }
//
// while (reader.MoveToNextEntry())
// {
// if (!reader.Entry.IsDirectory && Parser.Parser.IsImage(reader.Entry.Key))
// {
// count++;
// }
// }
// }
}
catch (Exception ex)
{
_logger.LogError(ex, "[GetNumberOfPagesFromArchive] There was an exception when reading archive stream: {ArchivePath}. Defaulting to 0 pages", archivePath);
return 0;
}
return count;
} }
public ArchiveMetadata GetArchiveData(string archivePath, bool createThumbnail)
{
return new ArchiveMetadata()
{
Pages = GetNumberOfPagesFromArchive(archivePath),
//Summary = GetSummaryInfo(archivePath),
CoverImage = GetCoverImage(archivePath, createThumbnail)
};
}
/// <summary> /// <summary>
/// Generates byte array of cover image. /// Generates byte array of cover image.
/// Given a path to a compressed file (zip, rar, cbz, cbr, etc), will ensure the first image is returned unless /// Given a path to a compressed file (zip, rar, cbz, cbr, etc), will ensure the first image is returned unless
@ -159,13 +111,10 @@ namespace API.Services
/// <returns></returns> /// <returns></returns>
public byte[] GetCoverImage(string archivePath, bool createThumbnail = false) public byte[] GetCoverImage(string archivePath, bool createThumbnail = false)
{ {
if (archivePath == null || !IsValidArchive(archivePath)) return Array.Empty<byte>();
try try
{ {
if (!IsValidArchive(archivePath)) return Array.Empty<byte>(); var libraryHandler = CanOpen(archivePath);
var libraryHandler = Archive.Archive.CanOpen(archivePath);
switch (libraryHandler) switch (libraryHandler)
{ {
case ArchiveLibrary.Default: case ArchiveLibrary.Default:
@ -228,26 +177,6 @@ namespace API.Services
return Array.Empty<byte>(); return Array.Empty<byte>();
} }
private byte[] CreateThumbnail(byte[] entry, string formatExtension = ".jpg")
{
if (!formatExtension.StartsWith("."))
{
formatExtension = "." + formatExtension;
}
// TODO: Validate if jpeg is same as jpg
try
{
using var thumbnail = Image.ThumbnailBuffer(entry, ThumbnailWidth);
return thumbnail.WriteToBuffer(formatExtension);
}
catch (Exception ex)
{
_logger.LogError(ex, "[CreateThumbnail] There was a critical error and prevented thumbnail generation. Defaulting to no cover image");
}
return Array.Empty<byte>();
}
private static byte[] ConvertEntryToByteArray(ZipArchiveEntry entry) private static byte[] ConvertEntryToByteArray(ZipArchiveEntry entry)
{ {
using var stream = entry.Open(); using var stream = entry.Open();
@ -272,6 +201,25 @@ namespace API.Services
archive.Entries.Any(e => e.FullName.Contains(Path.AltDirectorySeparatorChar)); archive.Entries.Any(e => e.FullName.Contains(Path.AltDirectorySeparatorChar));
} }
private byte[] CreateThumbnail(byte[] entry, string formatExtension = ".jpg")
{
if (!formatExtension.StartsWith("."))
{
formatExtension = "." + formatExtension;
}
// TODO: Validate if jpeg is same as jpg
try
{
using var thumbnail = Image.ThumbnailBuffer(entry, ThumbnailWidth);
return thumbnail.WriteToBuffer(formatExtension);
}
catch (Exception ex)
{
_logger.LogError(ex, "[CreateThumbnail] There was a critical error and prevented thumbnail generation. Defaulting to no cover image");
}
return Array.Empty<byte>();
}
private byte[] CreateThumbnail(ZipArchiveEntry entry, string formatExtension = ".jpg") private byte[] CreateThumbnail(ZipArchiveEntry entry, string formatExtension = ".jpg")
{ {
@ -344,7 +292,7 @@ namespace API.Services
{ {
if (!File.Exists(archivePath)) return summary; if (!File.Exists(archivePath)) return summary;
var libraryHandler = Archive.Archive.CanOpen(archivePath); var libraryHandler = CanOpen(archivePath);
switch (libraryHandler) switch (libraryHandler)
{ {
case ArchiveLibrary.Default: case ArchiveLibrary.Default:
@ -403,9 +351,6 @@ namespace API.Services
Overwrite = false Overwrite = false
}); });
} }
// using ZipArchive archive = ZipFile.OpenRead(archivePath);
// archive.ExtractToDirectory(extractPath, true);
} }
private void ExtractArchiveEntries(ZipArchive archive, string extractPath) private void ExtractArchiveEntries(ZipArchive archive, string extractPath)
@ -431,7 +376,7 @@ namespace API.Services
/// <returns></returns> /// <returns></returns>
public void ExtractArchive(string archivePath, string extractPath) public void ExtractArchive(string archivePath, string extractPath)
{ {
if (!File.Exists(archivePath)) return; if (!IsValidArchive(archivePath)) return;
if (Directory.Exists(extractPath)) return; if (Directory.Exists(extractPath)) return;
@ -439,7 +384,7 @@ namespace API.Services
try try
{ {
var libraryHandler = Archive.Archive.CanOpen(archivePath); var libraryHandler = CanOpen(archivePath);
switch (libraryHandler) switch (libraryHandler)
{ {
case ArchiveLibrary.Default: case ArchiveLibrary.Default:
@ -473,4 +418,5 @@ namespace API.Services
_logger.LogDebug("Extracted archive to {ExtractPath} in {ElapsedMilliseconds} milliseconds", extractPath, sw.ElapsedMilliseconds); _logger.LogDebug("Extracted archive to {ExtractPath} in {ElapsedMilliseconds} milliseconds", extractPath, sw.ElapsedMilliseconds);
} }
} }
} }

View File

@ -97,6 +97,8 @@ namespace API.Services
/// <param name="directoryPath"></param> /// <param name="directoryPath"></param>
public static void ClearAndDeleteDirectory(string directoryPath) public static void ClearAndDeleteDirectory(string directoryPath)
{ {
if (!Directory.Exists(directoryPath)) return;
DirectoryInfo di = new DirectoryInfo(directoryPath); DirectoryInfo di = new DirectoryInfo(directoryPath);
ClearDirectory(directoryPath); ClearDirectory(directoryPath);