diff --git a/API.Tests/API.Tests.csproj b/API.Tests/API.Tests.csproj
index e19d7abc9..ec5ee39dd 100644
--- a/API.Tests/API.Tests.csproj
+++ b/API.Tests/API.Tests.csproj
@@ -23,4 +23,8 @@
+
+
+
+
diff --git a/API.Tests/ParserTest.cs b/API.Tests/ParserTest.cs
index 82c4a4892..320856c32 100644
--- a/API.Tests/ParserTest.cs
+++ b/API.Tests/ParserTest.cs
@@ -82,5 +82,15 @@ namespace API.Tests
{
Assert.Equal(expected, CleanTitle(input));
}
+
+ [Theory]
+ [InlineData("test.cbz", true)]
+ [InlineData("test.cbr", true)]
+ [InlineData("test.zip", true)]
+ [InlineData("test.rar", true)]
+ public void IsArchiveTest(string input, bool expected)
+ {
+ Assert.Equal(expected, IsArchive(input));
+ }
}
}
\ No newline at end of file
diff --git a/API.Tests/Services/ImageProviderTest.cs b/API.Tests/Services/ImageProviderTest.cs
new file mode 100644
index 000000000..eae737cb7
--- /dev/null
+++ b/API.Tests/Services/ImageProviderTest.cs
@@ -0,0 +1,21 @@
+using System;
+using System.IO;
+using API.IO;
+using Xunit;
+
+namespace API.Tests.Services
+{
+ public class ImageProviderTest
+ {
+ [Theory]
+ [InlineData("v10.cbz", "v10.expected.jpg")]
+ [InlineData("v10 - with folder.cbz", "v10 - with folder.expected.jpg")]
+ public void GetCoverImageTest(string inputFile, string expectedOutputFile)
+ {
+ var testDirectory = Path.Join(Directory.GetCurrentDirectory(), "../../../Services/Test Data/ImageProvider");
+ var expectedBytes = File.ReadAllBytes(Path.Join(testDirectory, expectedOutputFile));
+
+ Assert.Equal(expectedBytes, ImageProvider.GetCoverImage(Path.Join(testDirectory, inputFile)));
+ }
+ }
+}
\ No newline at end of file
diff --git a/API.Tests/Services/Test Data/ImageProvider/v10 - nested folder.cbz b/API.Tests/Services/Test Data/ImageProvider/v10 - nested folder.cbz
new file mode 100644
index 000000000..0d2886130
Binary files /dev/null and b/API.Tests/Services/Test Data/ImageProvider/v10 - nested folder.cbz differ
diff --git a/API.Tests/Services/Test Data/ImageProvider/v10 - nested folder.expected.jpg b/API.Tests/Services/Test Data/ImageProvider/v10 - nested folder.expected.jpg
new file mode 100644
index 000000000..51fd89ca0
Binary files /dev/null and b/API.Tests/Services/Test Data/ImageProvider/v10 - nested folder.expected.jpg differ
diff --git a/API.Tests/Services/Test Data/ImageProvider/v10 - with folder.cbz b/API.Tests/Services/Test Data/ImageProvider/v10 - with folder.cbz
new file mode 100644
index 000000000..013fddebc
Binary files /dev/null and b/API.Tests/Services/Test Data/ImageProvider/v10 - with folder.cbz differ
diff --git a/API.Tests/Services/Test Data/ImageProvider/v10 - with folder.expected.jpg b/API.Tests/Services/Test Data/ImageProvider/v10 - with folder.expected.jpg
new file mode 100644
index 000000000..888eeb5ec
Binary files /dev/null and b/API.Tests/Services/Test Data/ImageProvider/v10 - with folder.expected.jpg differ
diff --git a/API.Tests/Services/Test Data/ImageProvider/v10.cbz b/API.Tests/Services/Test Data/ImageProvider/v10.cbz
new file mode 100644
index 000000000..99fbfa400
Binary files /dev/null and b/API.Tests/Services/Test Data/ImageProvider/v10.cbz differ
diff --git a/API.Tests/Services/Test Data/ImageProvider/v10.expected.jpg b/API.Tests/Services/Test Data/ImageProvider/v10.expected.jpg
new file mode 100644
index 000000000..51fd89ca0
Binary files /dev/null and b/API.Tests/Services/Test Data/ImageProvider/v10.expected.jpg differ
diff --git a/API/IO/ImageProvider.cs b/API/IO/ImageProvider.cs
new file mode 100644
index 000000000..7a71c8813
--- /dev/null
+++ b/API/IO/ImageProvider.cs
@@ -0,0 +1,45 @@
+using System;
+using System.IO;
+using System.IO.Compression;
+using System.Linq;
+
+namespace API.IO
+{
+ public static class ImageProvider
+ {
+ ///
+ /// 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
+ /// a folder.extension exists in the root directory of the compressed file.
+ ///
+ ///
+ ///
+ public static byte[] GetCoverImage(string filepath)
+ {
+ if (!File.Exists(filepath) || !Parser.Parser.IsArchive(filepath)) return Array.Empty();
+
+ using ZipArchive archive = ZipFile.OpenRead(filepath);
+ if (archive.Entries.Count <= 0) return Array.Empty();
+
+ var folder = archive.Entries.SingleOrDefault(x => Path.GetFileNameWithoutExtension(x.Name).ToLower() == "folder");
+ var entry = archive.Entries[0];
+
+ if (folder != null)
+ {
+ entry = folder;
+ }
+
+ return ExtractEntryToImage(entry);
+ }
+
+ private static byte[] ExtractEntryToImage(ZipArchiveEntry entry)
+ {
+ var stream = entry.Open();
+ using var ms = new MemoryStream();
+ stream.CopyTo(ms);
+ var data = ms.ToArray();
+
+ return data;
+ }
+ }
+}
\ No newline at end of file
diff --git a/API/Parser/Parser.cs b/API/Parser/Parser.cs
index f0633c36e..b94f6f719 100644
--- a/API/Parser/Parser.cs
+++ b/API/Parser/Parser.cs
@@ -1,4 +1,5 @@
using System;
+using System.IO;
using System.Text.RegularExpressions;
namespace API.Parser
@@ -226,5 +227,12 @@ namespace API.Parser
{
return title.TrimStart(new[] { '0' });
}
+
+ public static bool IsArchive(string filePath)
+ {
+ var fileInfo = new FileInfo(filePath);
+
+ return MangaFileExtensions.Contains(fileInfo.Extension);
+ }
}
}
\ No newline at end of file
diff --git a/API/Services/DirectoryService.cs b/API/Services/DirectoryService.cs
index 958b4641e..85344f40e 100644
--- a/API/Services/DirectoryService.cs
+++ b/API/Services/DirectoryService.cs
@@ -4,13 +4,13 @@ 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;
using System.Threading.Tasks;
using API.Entities;
using API.Interfaces;
+using API.IO;
using API.Parser;
using Microsoft.Extensions.Logging;
@@ -183,7 +183,7 @@ namespace API.Services
{
Name = info.Volumes,
Number = Int32.Parse(info.Volumes),
- CoverImage = getCoverImage(info.FullFilePath),
+ CoverImage = ImageProvider.GetCoverImage(info.FullFilePath),
Files = new List()
{
new MangaFile()
@@ -352,31 +352,8 @@ namespace API.Services
Console.WriteLine("Processed {0} files in {1} milliseconds", fileCount, sw.ElapsedMilliseconds);
}
- ///
- /// Generates byte array of cover image.
- /// Looks for first valid image file (folder.png, first jpg/png file)
- ///
- ///
- ///
- private byte[] getCoverImage(string filepath)
- {
- // TODO: Sort and file type
- // if file not zip (folder or txt)
- using (ZipArchive archive = ZipFile.OpenRead(filepath))
- {
+
- if (archive.Entries.Count <= 0) {return null;}
- var stream = archive.Entries[0].Open();
- byte[] data;
- using (var ms = new MemoryStream())
- {
- stream.CopyTo(ms);
- data = ms.ToArray();
- }
-
- return data;
- }
-
- }
+
}
}
\ No newline at end of file