pull/1463/head^2
gedoor 3 years ago
parent 20ed460086
commit dba07bc9c8
  1. 22
      app/src/main/java/io/legado/app/help/BookHelp.kt
  2. 163
      app/src/main/java/io/legado/app/model/localBook/EpubFile.kt
  3. 3
      app/src/main/java/io/legado/app/model/localBook/LocalBook.kt

@ -1,6 +1,5 @@
package io.legado.app.help package io.legado.app.help
import android.net.Uri
import io.legado.app.constant.AppPattern import io.legado.app.constant.AppPattern
import io.legado.app.constant.EventBus import io.legado.app.constant.EventBus
import io.legado.app.data.appDb import io.legado.app.data.appDb
@ -24,9 +23,9 @@ import kotlin.math.min
@Suppress("unused") @Suppress("unused")
object BookHelp { object BookHelp {
private const val cacheFolderName = "book_cache" val downloadDir: File = appCtx.externalFiles
const val cacheFolderName = "book_cache"
private const val cacheImageFolderName = "images" private const val cacheImageFolderName = "images"
private val downloadDir: File = appCtx.externalFiles
private val downloadImages = CopyOnWriteArraySet<String>() private val downloadImages = CopyOnWriteArraySet<String>()
fun clearCache() { fun clearCache() {
@ -58,23 +57,6 @@ object BookHelp {
} }
} }
fun getEpubFile(book: Book): File {
val file = downloadDir.getFile(cacheFolderName, book.getFolderName(), "index.epubx")
if (!file.exists()) {
val input = if (book.bookUrl.isContentScheme()) {
val uri = Uri.parse(book.bookUrl)
appCtx.contentResolver.openInputStream(uri)
} else {
File(book.bookUrl).inputStream()
}
if (input != null) {
FileUtils.writeInputStream(file, input)
}
}
return file
}
suspend fun saveContent( suspend fun saveContent(
bookSource: BookSource, bookSource: BookSource,
book: Book, book: Book,

@ -2,15 +2,14 @@ package io.legado.app.model.localBook
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.net.Uri
import android.text.TextUtils import android.text.TextUtils
import io.legado.app.data.entities.Book import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.BookChapter
import io.legado.app.help.BookHelp import io.legado.app.help.BookHelp
import io.legado.app.utils.FileUtils import io.legado.app.utils.*
import io.legado.app.utils.HtmlFormatter
import io.legado.app.utils.MD5Utils
import io.legado.app.utils.externalFiles
import me.ag2s.epublib.domain.EpubBook import me.ag2s.epublib.domain.EpubBook
import me.ag2s.epublib.domain.TOCReference
import me.ag2s.epublib.epub.EpubReader import me.ag2s.epublib.epub.EpubReader
import org.jsoup.Jsoup import org.jsoup.Jsoup
import splitties.init.appCtx import splitties.init.appCtx
@ -28,10 +27,30 @@ class EpubFile(var book: Book) {
companion object { companion object {
private var eFile: EpubFile? = null private var eFile: EpubFile? = null
fun getFile(book: Book): File {
val file = BookHelp.downloadDir.getFile(
BookHelp.cacheFolderName,
book.getFolderName(),
"index.epubx"
)
if (!file.exists()) {
val input = if (book.bookUrl.isContentScheme()) {
val uri = Uri.parse(book.bookUrl)
appCtx.contentResolver.openInputStream(uri)
} else {
File(book.bookUrl).inputStream()
}
if (input != null) {
FileUtils.writeInputStream(file, input)
}
}
return file
}
@Synchronized @Synchronized
private fun getEFile(book: Book): EpubFile { private fun getEFile(book: Book): EpubFile {
BookHelp.getEpubFile(book) getFile(book)
if (eFile == null || eFile?.book?.bookUrl != book.bookUrl) { if (eFile == null || eFile?.book?.bookUrl != book.bookUrl) {
eFile = EpubFile(book) eFile = EpubFile(book)
//对于Epub文件默认不启用替换 //对于Epub文件默认不启用替换
@ -105,12 +124,9 @@ class EpubFile(var book: Book) {
/*重写epub文件解析代码,直接读出压缩包文件生成Resources给epublib,这样的好处是可以逐一修改某些文件的格式错误*/ /*重写epub文件解析代码,直接读出压缩包文件生成Resources给epublib,这样的好处是可以逐一修改某些文件的格式错误*/
private fun readEpub(): EpubBook? { private fun readEpub(): EpubBook? {
try { try {
val file = getFile(book)
val file = BookHelp.getEpubFile(book)
//通过懒加载读取epub //通过懒加载读取epub
return EpubReader().readEpubLazy(ZipFile(file), "utf-8") return EpubReader().readEpubLazy(ZipFile(file), "utf-8")
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e) Timber.e(e)
} }
@ -193,34 +209,121 @@ class EpubFile(var book: Book) {
private fun getChapterList(): ArrayList<BookChapter> { private fun getChapterList(): ArrayList<BookChapter> {
val chapterList = ArrayList<BookChapter>() val chapterList = ArrayList<BookChapter>()
epubBook?.tableOfContents?.allUniqueResources?.forEachIndexed { index, resource -> epubBook?.let { eBook ->
var title = resource.title val refs = eBook.tableOfContents.tocReferences
if (TextUtils.isEmpty(title)) { if (refs == null || refs.isEmpty()) {
try { val spineReferences = eBook.spine.spineReferences
val doc = var i = 0
Jsoup.parse(String(resource.data, mCharset)) val size = spineReferences.size
val elements = doc.getElementsByTag("title") while (i < size) {
if (elements.size > 0) { val resource = spineReferences[i].resource
title = elements[0].text() var title = resource.title
if (TextUtils.isEmpty(title)) {
try {
val doc =
Jsoup.parse(String(resource.data, mCharset))
val elements = doc.getElementsByTag("title")
if (elements.size > 0) {
title = elements[0].text()
}
} catch (e: IOException) {
e.printStackTrace()
}
} }
} catch (e: IOException) { val chapter = BookChapter()
Timber.e(e) chapter.index = i
chapter.bookUrl = book.bookUrl
chapter.url = resource.href
if (i == 0 && title.isEmpty()) {
chapter.title = "封面"
} else {
chapter.title = title
}
chapterList.add(chapter)
i++
} }
}
val chapter = BookChapter()
chapter.index = index
chapter.bookUrl = book.bookUrl
chapter.url = resource.href
if (index == 0 && title.isEmpty()) {
chapter.title = "封面"
} else { } else {
chapter.title = title parseFirstPage(chapterList, refs)
parseMenu(chapterList, refs, 0)
for (i in chapterList.indices) {
chapterList[i].index = i
}
} }
chapterList.add(chapter)
} }
book.latestChapterTitle = chapterList.lastOrNull()?.title book.latestChapterTitle = chapterList.lastOrNull()?.title
book.totalChapterNum = chapterList.size book.totalChapterNum = chapterList.size
return chapterList return chapterList
} }
/*获取书籍起始页内容。部分书籍第一章之前存在封面,引言,扉页等内容*/
/*tile获取不同书籍风格杂乱,格式化处理待优化*/
private var durIndex = 0
private fun parseFirstPage(
chapterList: ArrayList<BookChapter>,
refs: List<TOCReference>?
) {
val contents = epubBook?.contents
if (epubBook == null || contents == null || refs == null) return
var i = 0
durIndex = 0
while (i < contents.size) {
val content = contents[i]
if (!content.mediaType.toString().contains("htm")) continue
/*检索到第一章href停止*/
if (refs[0].completeHref == content.href) break
val chapter = BookChapter()
var title = content.title
if (TextUtils.isEmpty(title)) {
val elements = Jsoup.parse(
String(
epubBook!!.resources.getByHref(content.href).data,
mCharset
)
).getElementsByTag("title")
title =
if (elements.size > 0 && elements[0].text()
.isNotBlank()
) elements[0].text() else "--卷首--"
}
chapter.bookUrl = book.bookUrl
chapter.title = title
chapter.url = content.href
chapter.startFragmentId =
if (content.href.substringAfter("#") == content.href) null
else content.href.substringAfter("#")
if (durIndex > 0) {
val preIndex = durIndex - 1
chapterList[preIndex].endFragmentId = chapter.startFragmentId
}
chapterList.add(chapter)
durIndex++
i++
}
}
private fun parseMenu(
chapterList: ArrayList<BookChapter>,
refs: List<TOCReference>?,
level: Int
) {
refs?.forEach { ref ->
if (ref.resource != null) {
val chapter = BookChapter()
chapter.bookUrl = book.bookUrl
chapter.title = ref.title
chapter.url = ref.completeHref
chapter.startFragmentId = ref.fragmentId
if (durIndex > 0) {
val preIndex = durIndex - 1
chapterList[preIndex].endFragmentId = chapter.startFragmentId
}
chapterList.add(chapter)
durIndex++
}
if (ref.children != null && ref.children.isNotEmpty()) {
parseMenu(chapterList, ref.children, level + 1)
}
}
}
} }

@ -151,11 +151,10 @@ object LocalBook {
bookFile.delete() bookFile.delete()
} }
if (book.isEpub()) { if (book.isEpub()) {
val bookFile = BookHelp.getEpubFile(book).parentFile val bookFile = EpubFile.getFile(book).parentFile
if (bookFile != null && bookFile.exists()) { if (bookFile != null && bookFile.exists()) {
FileUtils.delete(bookFile, true) FileUtils.delete(bookFile, true)
} }
} }
if (deleteOriginal) { if (deleteOriginal) {

Loading…
Cancel
Save