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. 131
      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
import android.net.Uri
import io.legado.app.constant.AppPattern
import io.legado.app.constant.EventBus
import io.legado.app.data.appDb
@ -24,9 +23,9 @@ import kotlin.math.min
@Suppress("unused")
object BookHelp {
private const val cacheFolderName = "book_cache"
val downloadDir: File = appCtx.externalFiles
const val cacheFolderName = "book_cache"
private const val cacheImageFolderName = "images"
private val downloadDir: File = appCtx.externalFiles
private val downloadImages = CopyOnWriteArraySet<String>()
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(
bookSource: BookSource,
book: Book,

@ -2,15 +2,14 @@ package io.legado.app.model.localBook
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.text.TextUtils
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter
import io.legado.app.help.BookHelp
import io.legado.app.utils.FileUtils
import io.legado.app.utils.HtmlFormatter
import io.legado.app.utils.MD5Utils
import io.legado.app.utils.externalFiles
import io.legado.app.utils.*
import me.ag2s.epublib.domain.EpubBook
import me.ag2s.epublib.domain.TOCReference
import me.ag2s.epublib.epub.EpubReader
import org.jsoup.Jsoup
import splitties.init.appCtx
@ -28,10 +27,30 @@ class EpubFile(var book: Book) {
companion object {
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
private fun getEFile(book: Book): EpubFile {
BookHelp.getEpubFile(book)
getFile(book)
if (eFile == null || eFile?.book?.bookUrl != book.bookUrl) {
eFile = EpubFile(book)
//对于Epub文件默认不启用替换
@ -105,12 +124,9 @@ class EpubFile(var book: Book) {
/*重写epub文件解析代码,直接读出压缩包文件生成Resources给epublib,这样的好处是可以逐一修改某些文件的格式错误*/
private fun readEpub(): EpubBook? {
try {
val file = BookHelp.getEpubFile(book)
val file = getFile(book)
//通过懒加载读取epub
return EpubReader().readEpubLazy(ZipFile(file), "utf-8")
} catch (e: Exception) {
Timber.e(e)
}
@ -193,7 +209,14 @@ class EpubFile(var book: Book) {
private fun getChapterList(): ArrayList<BookChapter> {
val chapterList = ArrayList<BookChapter>()
epubBook?.tableOfContents?.allUniqueResources?.forEachIndexed { index, resource ->
epubBook?.let { eBook ->
val refs = eBook.tableOfContents.tocReferences
if (refs == null || refs.isEmpty()) {
val spineReferences = eBook.spine.spineReferences
var i = 0
val size = spineReferences.size
while (i < size) {
val resource = spineReferences[i].resource
var title = resource.title
if (TextUtils.isEmpty(title)) {
try {
@ -204,23 +227,103 @@ class EpubFile(var book: Book) {
title = elements[0].text()
}
} catch (e: IOException) {
Timber.e(e)
e.printStackTrace()
}
}
val chapter = BookChapter()
chapter.index = index
chapter.index = i
chapter.bookUrl = book.bookUrl
chapter.url = resource.href
if (index == 0 && title.isEmpty()) {
if (i == 0 && title.isEmpty()) {
chapter.title = "封面"
} else {
chapter.title = title
}
chapterList.add(chapter)
i++
}
} else {
parseFirstPage(chapterList, refs)
parseMenu(chapterList, refs, 0)
for (i in chapterList.indices) {
chapterList[i].index = i
}
}
}
book.latestChapterTitle = chapterList.lastOrNull()?.title
book.totalChapterNum = chapterList.size
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()
}
if (book.isEpub()) {
val bookFile = BookHelp.getEpubFile(book).parentFile
val bookFile = EpubFile.getFile(book).parentFile
if (bookFile != null && bookFile.exists()) {
FileUtils.delete(bookFile, true)
}
}
if (deleteOriginal) {

Loading…
Cancel
Save