fix(epub): epub were not loading properly on Windows

fixes #149
This commit is contained in:
Gauthier Roebroeck 2020-05-04 15:25:29 +08:00
parent a56b5a624a
commit eca453c534

View file

@ -2,6 +2,7 @@ package org.gotson.komga.infrastructure.mediacontainer
import mu.KotlinLogging import mu.KotlinLogging
import org.apache.commons.compress.archivers.zip.ZipFile import org.apache.commons.compress.archivers.zip.ZipFile
import org.apache.commons.io.FilenameUtils
import org.gotson.komga.domain.model.MediaContainerEntry import org.gotson.komga.domain.model.MediaContainerEntry
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
@ -18,29 +19,29 @@ class EpubExtractor(contentDetector: ContentDetector) : ZipExtractor(contentDete
override fun getEntries(path: Path): List<MediaContainerEntry> { override fun getEntries(path: Path): List<MediaContainerEntry> {
ZipFile(path.toFile()).use { zip -> ZipFile(path.toFile()).use { zip ->
try { try {
val packagePath = getPackagePath(zip) val opfFile = getPackagePath(zip)
val opf = zip.getInputStream(zip.getEntry(packagePath)).use { Jsoup.parse(it, null, "") } val opfDoc = zip.getInputStream(zip.getEntry(opfFile)).use { Jsoup.parse(it, null, "") }
val opfPath = Paths.get(packagePath).parentOrEmpty() val opfDir = Paths.get(opfFile).parentOrEmpty()
val manifest = opf.select("manifest > item") val manifest = opfDoc.select("manifest > item")
.associate { it.attr("id") to ManifestItem(it.attr("id"), it.attr("href"), it.attr("media-type")) } .associate { it.attr("id") to ManifestItem(it.attr("id"), it.attr("href"), it.attr("media-type")) }
val pages = opf.select("spine > itemref").map { it.attr("idref") } val pages = opfDoc.select("spine > itemref").map { it.attr("idref") }
.mapNotNull { manifest[it] } .mapNotNull { manifest[it] }
.map { it.href } .map { it.href }
val images = pages val images = pages
.map { opfPath.resolve(it).normalize() } .map { opfDir.resolve(it).normalize() }
.flatMap { pagePath -> .flatMap { pagePath ->
val doc = zip.getInputStream(zip.getEntry(pagePath.toString())).use { Jsoup.parse(it, null, "") } val doc = zip.getInputStream(zip.getEntry(pagePath.separatorsToUnix())).use { Jsoup.parse(it, null, "") }
doc.getElementsByTag("img") doc.getElementsByTag("img")
.map { it.attr("src") } .map { it.attr("src") }
.map { pagePath.parentOrEmpty().resolve(it).normalize() } .map { pagePath.parentOrEmpty().resolve(it).normalize() }
} }
return images.map { image -> return images.map { image ->
MediaContainerEntry(image.toString(), manifest.values.first { it.href == opfPath.relativize(image).toString() }.mediaType) MediaContainerEntry(image.toString(), manifest.values.first { it.href == opfDir.relativize(image).separatorsToUnix() }.mediaType)
} }
} catch (e: Exception) { } catch (e: Exception) {
logger.error(e) { "File is not a proper Epub, treating it as a zip file" } logger.error(e) { "File is not a proper Epub, treating it as a zip file" }
@ -56,15 +57,17 @@ class EpubExtractor(contentDetector: ContentDetector) : ZipExtractor(contentDete
} }
fun getPackageFile(path: Path): String? = fun getPackageFile(path: Path): String? =
ZipFile(path.toFile()).use { ZipFile(path.toFile()).use { zip ->
try { try {
it.getInputStream(it.getEntry(getPackagePath(it))).reader().use { it.readText() } zip.getInputStream(zip.getEntry(getPackagePath(zip))).reader().use { it.readText() }
} catch (e: Exception) { } catch (e: Exception) {
null null
} }
} }
fun Path.parentOrEmpty() = parent ?: Paths.get("") fun Path.parentOrEmpty(): Path = parent ?: Paths.get("")
fun Path.separatorsToUnix(): String = FilenameUtils.separatorsToUnix(this.toString())
private data class ManifestItem( private data class ManifestItem(
val id: String, val id: String,