feat: download current page from webreader

closes #469
This commit is contained in:
Gauthier Roebroeck 2021-03-24 16:26:38 +08:00
parent 84ff250030
commit 93cec4e4e5
6 changed files with 55 additions and 1 deletions

View file

@ -12,6 +12,7 @@
"core-js": "^3.6.5",
"date-fns": "^2.19.0",
"jquery": "^3.5.1",
"js-file-downloader": "^1.1.16",
"language-tags": "^1.0.5",
"lodash": "^4.17.19",
"qs": "^6.9.4",
@ -13480,6 +13481,11 @@
"node": ">=10"
}
},
"node_modules/js-file-downloader": {
"version": "1.1.16",
"resolved": "https://registry.npmjs.org/js-file-downloader/-/js-file-downloader-1.1.16.tgz",
"integrity": "sha512-vj4ZpHvFJI7J7SluyreHzaAVZDrPulRcwjMMOUve1KOEB4oxYAiQZXzgmu2lPbMTqKlf7U91MNZYRMTq7DsMfQ=="
},
"node_modules/js-message": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.5.tgz",
@ -32242,6 +32248,11 @@
}
}
},
"js-file-downloader": {
"version": "1.1.16",
"resolved": "https://registry.npmjs.org/js-file-downloader/-/js-file-downloader-1.1.16.tgz",
"integrity": "sha512-vj4ZpHvFJI7J7SluyreHzaAVZDrPulRcwjMMOUve1KOEB4oxYAiQZXzgmu2lPbMTqKlf7U91MNZYRMTq7DsMfQ=="
},
"js-message": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.5.tgz",

View file

@ -15,6 +15,7 @@
"core-js": "^3.6.5",
"date-fns": "^2.19.0",
"jquery": "^3.5.1",
"js-file-downloader": "^1.1.16",
"language-tags": "^1.0.5",
"lodash": "^4.17.19",
"qs": "^6.9.4",

View file

@ -37,6 +37,7 @@
"cycling_page_layout": "Cycling Page Layout",
"cycling_scale": "Cycling Scale",
"cycling_side_padding": "Cycling Side Padding",
"download_current_page": "Download current page",
"end_of_book": "You've reached the end of the book.",
"from_series_metadata": "from series metadata",
"move_next": "Click or press \"Next\" again to move to the next book.",

View file

@ -38,6 +38,19 @@
>
<v-icon>mdi-cog</v-icon>
</v-btn>
<v-menu offset-y>
<template v-slot:activator="{ on }">
<v-btn icon v-on="on" @click.prevent="">
<v-icon>mdi-dots-vertical</v-icon>
</v-btn>
</template>
<v-list>
<v-list-item @click="downloadCurrentPage">
<v-list-item-title>{{ $t('bookreader.download_current_page') }}</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</v-toolbar>
</v-slide-y-transition>
@ -290,6 +303,7 @@ import {shortcutsSettingsContinuous} from '@/functions/shortcuts/continuous-read
import {BookDto, PageDto, PageDtoWithUrl} from '@/types/komga-books'
import {Context, ContextOrigin} from '@/types/context'
import {SeriesDto} from "@/types/komga-series";
import jsFileDownloader from "js-file-downloader"
const cookieFit = 'webreader.fit'
const cookieContinuousReaderFit = 'webreader.continuousReaderFit'
@ -484,6 +498,9 @@ export default Vue.extend({
contextReadList (): boolean {
return this.context.origin === ContextOrigin.READLIST
},
currentPage(): PageDtoWithUrl {
return this.pages[this.page - 1]
},
animations: {
get: function (): boolean {
@ -782,6 +799,12 @@ export default Vue.extend({
async markProgress (page: number) {
await this.$komgaBooks.updateReadProgress(this.bookId, { page: page })
},
downloadCurrentPage() {
new jsFileDownloader({
url: this.currentPage.url,
withCredentials: true,
})
},
},
})
</script>

View file

@ -36,4 +36,11 @@ class ContentDetector(
fun isImage(mediaType: String): Boolean =
mediaType.startsWith("image/")
fun mediaTypeToExtension(mediaType: String): String? =
try {
tika.mimeRepository.forName(mediaType).extension
} catch (e: Exception) {
null
}
}

View file

@ -24,6 +24,7 @@ import org.gotson.komga.domain.persistence.ReadListRepository
import org.gotson.komga.domain.service.BookLifecycle
import org.gotson.komga.infrastructure.image.ImageType
import org.gotson.komga.infrastructure.jooq.UnpagedSorted
import org.gotson.komga.infrastructure.mediacontainer.ContentDetector
import org.gotson.komga.infrastructure.security.KomgaPrincipal
import org.gotson.komga.infrastructure.swagger.PageableAsQueryParam
import org.gotson.komga.infrastructure.swagger.PageableWithoutSortAsQueryParam
@ -78,7 +79,8 @@ class BookController(
private val bookMetadataRepository: BookMetadataRepository,
private val mediaRepository: MediaRepository,
private val bookDtoRepository: BookDtoRepository,
private val readListRepository: ReadListRepository
private val readListRepository: ReadListRepository,
private val contentDetector: ContentDetector,
) {
@PageableAsQueryParam
@ -342,6 +344,15 @@ class BookController(
val pageContent = bookLifecycle.getBookPage(book, pageNum, convertFormat)
ResponseEntity.ok()
.headers(
HttpHeaders().apply {
val extension = contentDetector.mediaTypeToExtension(pageContent.mediaType) ?: "jpeg"
val imageFileName = "${book.name}-$pageNum$extension"
contentDisposition = ContentDisposition.builder("inline")
.filename(imageFileName)
.build()
}
)
.contentType(getMediaTypeOrDefault(pageContent.mediaType))
.setNotModified(media)
.body(pageContent.content)