properly close streams to avoid file/folder locking

This commit is contained in:
Gauthier Roebroeck 2019-08-20 16:51:13 +08:00
parent 89c3b50bb0
commit 70cc75da72
6 changed files with 62 additions and 60 deletions

View file

@ -11,7 +11,6 @@ import org.gotson.komga.infrastructure.archive.RarExtractor
import org.gotson.komga.infrastructure.archive.ZipExtractor
import org.springframework.stereotype.Service
import java.io.ByteArrayOutputStream
import java.io.InputStream
private val logger = KotlinLogging.logger {}
@ -42,12 +41,14 @@ class BookParser(
logger.info { "Book has ${pages.size} pages" }
val thumbnail = try {
ByteArrayOutputStream().let {
Thumbnails.of(supportedMediaTypes.getValue(mediaType).getPageStream(book.path(), pages.first().fileName))
.size(thumbnailSize, thumbnailSize)
.outputFormat(thumbnailFormat)
.toOutputStream(it)
it.toByteArray()
ByteArrayOutputStream().use {
supportedMediaTypes.getValue(mediaType).getPageStream(book.path(), pages.first().fileName).let { cover ->
Thumbnails.of(cover.inputStream())
.size(thumbnailSize, thumbnailSize)
.outputFormat(thumbnailFormat)
.toOutputStream(it)
it.toByteArray()
}
}
} catch (ex: Exception) {
logger.warn(ex) { "Could not generate thumbnail for book: ${book.url}" }
@ -57,7 +58,7 @@ class BookParser(
return BookMetadata(mediaType = mediaType, status = Status.READY, pages = pages.toMutableList(), thumbnail = thumbnail)
}
fun getPageStream(book: Book, number: Int): InputStream {
fun getPageContent(book: Book, number: Int): ByteArray {
logger.info { "Get page #$number for book: ${book.url}" }
if (book.metadata.status != Status.READY) {

View file

@ -2,7 +2,6 @@ package org.gotson.komga.infrastructure.archive
import net.greypanther.natsort.CaseInsensitiveSimpleNaturalComparator
import org.gotson.komga.domain.model.BookPage
import java.io.InputStream
import java.nio.file.Path
import java.util.*
@ -10,5 +9,5 @@ abstract class ArchiveExtractor {
protected val natSortComparator: Comparator<String> = CaseInsensitiveSimpleNaturalComparator.getInstance()
abstract fun getPagesList(path: Path): List<BookPage>
abstract fun getPageStream(path: Path, entryName: String): InputStream
abstract fun getPageStream(path: Path, entryName: String): ByteArray
}

View file

@ -19,18 +19,21 @@ class ContentDetector(
val metadata = Metadata().also {
it[Metadata.RESOURCE_NAME_KEY] = path.fileName.toString()
}
val mediaType = tika.detector.detect(TikaInputStream.get(path), metadata)
return mediaType.toString()
}
fun detectMediaType(stream: InputStream): String {
stream.use {
val mediaType = tika.detector.detect(TikaInputStream.get(it), Metadata())
return mediaType.toString()
return TikaInputStream.get(path).use {
val mediaType = tika.detector.detect(it, metadata)
mediaType.toString()
}
}
fun detectMediaType(stream: InputStream): String =
stream.use {
TikaInputStream.get(it).use { tikaStream ->
val mediaType = tika.detector.detect(tikaStream, Metadata())
mediaType.toString()
}
}
fun isImage(mediaType: String): Boolean =
mediaType.startsWith("image/")
}

View file

@ -3,7 +3,6 @@ package org.gotson.komga.infrastructure.archive
import com.github.junrar.Archive
import org.gotson.komga.domain.model.BookPage
import org.springframework.stereotype.Service
import java.io.InputStream
import java.nio.file.Files
import java.nio.file.Path
@ -12,26 +11,25 @@ class RarExtractor(
private val contentDetector: ContentDetector
) : ArchiveExtractor() {
override fun getPagesList(path: Path): List<BookPage> {
val rar = Archive(Files.newInputStream(path))
override fun getPagesList(path: Path): List<BookPage> =
Archive(Files.newInputStream(path)).use { rar ->
rar.fileHeaders
.filter { !it.isDirectory }
.map {
BookPage(
it.fileNameString,
contentDetector.detectMediaType(rar.getInputStream(it))
)
}
.filter { contentDetector.isImage(it.mediaType) }
.sortedWith(
compareBy(natSortComparator) { it.fileName }
)
}
return rar.fileHeaders
.filter { !it.isDirectory }
.map {
BookPage(
it.fileNameString,
contentDetector.detectMediaType(rar.getInputStream(it))
)
}
.filter { contentDetector.isImage(it.mediaType) }
.sortedWith(
compareBy(natSortComparator) { it.fileName }
)
}
override fun getPageStream(path: Path, entryName: String): InputStream {
val archive = Archive(Files.newInputStream(path))
val header = archive.fileHeaders.find { it.fileNameString == entryName }
return archive.getInputStream(header)
}
override fun getPageStream(path: Path, entryName: String): ByteArray =
Archive(Files.newInputStream(path)).use { rar ->
val header = rar.fileHeaders.find { it.fileNameString == entryName }
rar.getInputStream(header).readBytes()
}
}

View file

@ -2,7 +2,6 @@ package org.gotson.komga.infrastructure.archive
import org.gotson.komga.domain.model.BookPage
import org.springframework.stereotype.Service
import java.io.InputStream
import java.nio.file.Path
import java.util.zip.ZipFile
@ -11,24 +10,24 @@ class ZipExtractor(
private val contentDetector: ContentDetector
) : ArchiveExtractor() {
override fun getPagesList(path: Path): List<BookPage> {
val zip = ZipFile(path.toFile())
return zip.entries().toList()
.filter { !it.isDirectory }
.map {
BookPage(
it.name,
contentDetector.detectMediaType(zip.getInputStream(it))
)
}
.filter { contentDetector.isImage(it.mediaType) }
.sortedWith(
compareBy(natSortComparator) { it.fileName }
)
}
override fun getPagesList(path: Path): List<BookPage> =
ZipFile(path.toFile()).use { zip ->
zip.entries().toList()
.filter { !it.isDirectory }
.map {
BookPage(
it.name,
contentDetector.detectMediaType(zip.getInputStream(it))
)
}
.filter { contentDetector.isImage(it.mediaType) }
.sortedWith(
compareBy(natSortComparator) { it.fileName }
)
}
override fun getPageStream(path: Path, entryName: String): InputStream =
ZipFile(path.toFile()).let {
it.getInputStream(it.getEntry(entryName))
override fun getPageStream(path: Path, entryName: String): ByteArray =
ZipFile(path.toFile()).use {
it.getInputStream(it.getEntry(entryName)).readBytes()
}
}

View file

@ -9,7 +9,9 @@ import org.gotson.komga.domain.persistence.SerieRepository
import org.gotson.komga.domain.service.BookParser
import org.gotson.komga.domain.service.MetadataNotReadyException
import org.springframework.data.domain.Page
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Pageable
import org.springframework.data.domain.Sort
import org.springframework.data.repository.findByIdOrNull
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
@ -121,7 +123,7 @@ class SerieController(
try {
return bookRepository.findByIdOrNull((bookId))?.let { book ->
val pageContent = bookParser.getPageStream(book, pageNumber).readBytes()
val pageContent = bookParser.getPageContent(book, pageNumber)
val mediaType = try {
MediaType.parseMediaType(book.metadata.pages[pageNumber - 1].mediaType)