diff --git a/app/src/main/assets/web/bookSource/index.html b/app/src/main/assets/web/bookSource/index.html index c3b6a4389..c67a810f7 100644 --- a/app/src/main/assets/web/bookSource/index.html +++ b/app/src/main/assets/web/bookSource/index.html @@ -25,7 +25,7 @@
源类型 :
+ placeholder="<必填>0:文本 1:音频 2:图片 3:文件(只提供下载的网站)">
源名称 :
diff --git a/app/src/main/java/io/legado/app/api/controller/BookController.kt b/app/src/main/java/io/legado/app/api/controller/BookController.kt index 9254585f1..797212544 100644 --- a/app/src/main/java/io/legado/app/api/controller/BookController.kt +++ b/app/src/main/java/io/legado/app/api/controller/BookController.kt @@ -1,9 +1,7 @@ package io.legado.app.api.controller import android.net.Uri -import android.util.Base64 import androidx.core.graphics.drawable.toBitmap -import androidx.documentfile.provider.DocumentFile import io.legado.app.api.ReturnData import io.legado.app.constant.PreferKey import io.legado.app.data.appDb @@ -12,7 +10,6 @@ import io.legado.app.data.entities.BookSource import io.legado.app.help.BookHelp import io.legado.app.help.CacheManager import io.legado.app.help.ContentProcessor -import io.legado.app.help.config.AppConfig import io.legado.app.help.glide.ImageLoader import io.legado.app.help.storage.AppWebDav import io.legado.app.model.BookCover @@ -27,7 +24,6 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.runBlocking import splitties.init.appCtx import java.io.File -import java.io.FileOutputStream object BookController { @@ -248,45 +244,7 @@ object BookController { val fileData = parameters["fileData"]?.firstOrNull() ?: return returnData.setErrorMsg("fileData 不能为空") kotlin.runCatching { - val defaultBookTreeUri = AppConfig.defaultBookTreeUri - if (defaultBookTreeUri.isNullOrBlank()) return returnData.setErrorMsg("没有设置书籍保存位置!") - val treeUri = Uri.parse(defaultBookTreeUri) - val fileBytes = - Base64.decode(fileData.substringAfter("base64,"), Base64.DEFAULT) - val uri = if (treeUri.isContentScheme()) { - val treeDoc = DocumentFile.fromTreeUri(appCtx, treeUri) - var doc = treeDoc!!.findFile(fileName) - if (doc == null) { - doc = treeDoc.createFile(FileUtils.getMimeType(fileName), fileName) - ?: throw SecurityException("Permission Denial") - } - appCtx.contentResolver.openOutputStream(doc.uri)!!.use { oStream -> - oStream.write(fileBytes) - } - doc.uri - } else { - val treeFile = File(treeUri.path!!) - val file = treeFile.getFile(fileName) - FileOutputStream(file).use { oStream -> - oStream.write(fileBytes) - } - Uri.fromFile(file) - } - val nameAuthor = LocalBook.analyzeNameAuthor(fileName) - val book = Book( - bookUrl = uri.toString(), - name = nameAuthor.first, - author = nameAuthor.second, - originName = fileName, - coverUrl = FileUtils.getPath( - appCtx.externalFiles, - "covers", - "${MD5Utils.md5Encode16(uri.toString())}.jpg" - ) - ) - if (book.isEpub()) EpubFile.upBookInfo(book) - if (book.isUmd()) UmdFile.upBookInfo(book) - appDb.bookDao.insert(book) + LocalBook.importFile(fileData, fileName) }.onFailure { return when (it) { is SecurityException -> returnData.setErrorMsg("需重新设置书籍保存位置!") diff --git a/app/src/main/java/io/legado/app/constant/BookType.kt b/app/src/main/java/io/legado/app/constant/BookType.kt index 848884275..13c21f4ae 100644 --- a/app/src/main/java/io/legado/app/constant/BookType.kt +++ b/app/src/main/java/io/legado/app/constant/BookType.kt @@ -5,7 +5,8 @@ import androidx.annotation.IntDef object BookType { const val default = 0 // 0 文本 const val audio = 1 // 1 音频 - const val image = 2 //图片 + const val image = 2 // 2 图片 + const val file = 3 // 3 只提供下载服务的网站 const val local = "loc_book" @Target(AnnotationTarget.VALUE_PARAMETER) diff --git a/app/src/main/java/io/legado/app/data/entities/BookSource.kt b/app/src/main/java/io/legado/app/data/entities/BookSource.kt index 2d1d164c7..228ba7915 100644 --- a/app/src/main/java/io/legado/app/data/entities/BookSource.kt +++ b/app/src/main/java/io/legado/app/data/entities/BookSource.kt @@ -27,7 +27,7 @@ data class BookSource( var bookSourceName: String = "", // 分组 var bookSourceGroup: String? = null, - // 类型,0 文本,1 音频, 2 图片 + // 类型,0 文本,1 音频, 2 图片, 3 文件(指的是类似知轩藏书只提供下载的网站) @BookType.Type var bookSourceType: Int = 0, // 详情页url正则 diff --git a/app/src/main/java/io/legado/app/help/JsExtensions.kt b/app/src/main/java/io/legado/app/help/JsExtensions.kt index e2c935f76..0d1c117a3 100644 --- a/app/src/main/java/io/legado/app/help/JsExtensions.kt +++ b/app/src/main/java/io/legado/app/help/JsExtensions.kt @@ -197,12 +197,10 @@ interface JsExtensions { *js实现读取cookie */ fun getCookie(tag: String, key: String? = null): String { - val cookie = CookieStore.getCookie(tag) - val cookieMap = CookieStore.cookieToMap(cookie) return if (key != null) { - cookieMap[key] ?: "" + CookieStore.getKey(tag, key) } else { - cookie + CookieStore.getCookie(tag) } } @@ -470,10 +468,8 @@ interface JsExtensions { * @return zip指定文件的数据 */ fun getZipByteArrayContent(url: String, path: String): ByteArray? { - val bytes = if (url.startsWith("http://") || url.startsWith("https://")) { - runBlocking { - return@runBlocking okHttpClient.newCallResponseBody { url(url) }.bytes() - } + val bytes = if (url.isAbsUrl()) { + AnalyzeUrl(url, source = getSource()).getByteArray() } else { StringUtils.hexStringToByte(url) } @@ -517,7 +513,7 @@ interface JsExtensions { str.isAbsUrl() -> runBlocking { var x = CacheManager.getByteArray(key) if (x == null) { - x = okHttpClient.newCallResponseBody { url(str) }.bytes() + x = AnalyzeUrl(str, source = getSource()).getByteArray() x.let { CacheManager.put(key, it) } diff --git a/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt b/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt index 2b96dcfce..b1cc82a4a 100644 --- a/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt +++ b/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt @@ -1,6 +1,7 @@ package io.legado.app.model.localBook import android.net.Uri +import android.util.Base64 import androidx.documentfile.provider.DocumentFile import com.script.SimpleBindings import io.legado.app.R @@ -8,13 +9,17 @@ import io.legado.app.constant.AppConst import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter +import io.legado.app.data.entities.BaseSource import io.legado.app.exception.TocEmptyException +import io.legado.app.exception.NoStackTraceException import io.legado.app.help.BookHelp import io.legado.app.help.config.AppConfig +import io.legado.app.model.analyzeRule.AnalyzeUrl import io.legado.app.utils.* import splitties.init.appCtx import java.io.File import java.io.FileInputStream +import java.io.FileOutputStream import java.io.FileNotFoundException import java.io.InputStream import java.util.regex.Pattern @@ -79,6 +84,32 @@ object LocalBook { } } + //导入在线的文件 + fun importFile( + str: String, + fileName: String, + source: BaseSource? = null + ): Book { + val bytes = when { + str.isAbsUrl() -> AnalyzeUrl(str, source = source).getByteArray() + str.isDataUrl() -> Base64.decode(str.substringAfter("base64,"), Base64.DEFAULT) + else -> throw NoStackTraceException("在线导入书籍支持http/https/DataURL") + } + //从文件头识别文件格式 + + return importFile(bytes, fileName) + } + + fun importFile( + bytes: ByteArray, + fileName: String + ): Book { + return saveBookFile(bytes, fileName).let { + importFile(it) + } + } + + //导入本地文件 fun importFile(uri: Uri): Book { val bookUrl: String val updateTime: Long @@ -119,7 +150,7 @@ object LocalBook { return book } - fun analyzeNameAuthor(fileName: String): Pair { + private fun analyzeNameAuthor(fileName: String): Pair { val tempFileName = fileName.substringBeforeLast(".") var name: String var author: String @@ -171,4 +202,32 @@ object LocalBook { } } } + + private fun saveBookFile( + bytes: ByteArray, + fileName: String + ): Uri { + val defaultBookTreeUri = AppConfig.defaultBookTreeUri + if (defaultBookTreeUri.isNullOrBlank()) throw NoStackTraceException("没有设置书籍保存位置!") + val treeUri = Uri.parse(defaultBookTreeUri) + return if (treeUri.isContentScheme()) { + val treeDoc = DocumentFile.fromTreeUri(appCtx, treeUri) + var doc = treeDoc!!.findFile(fileName) + if (doc == null) { + doc = treeDoc.createFile(FileUtils.getMimeType(fileName), fileName) + ?: throw SecurityException("Permission Denial") + } + appCtx.contentResolver.openOutputStream(doc.uri)!!.use { oStream -> + oStream.write(bytes) + } + doc.uri + } else { + val treeFile = File(treeUri.path!!) + val file = treeFile.getFile(fileName) + FileOutputStream(file).use { oStream -> + oStream.write(bytes) + } + Uri.fromFile(file) + } + } } diff --git a/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt b/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt index 9b58c9a44..3f647fa46 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt @@ -192,6 +192,7 @@ class BookSourceEditActivity : binding.cbIsEnableFind.isChecked = it.enabledExplore binding.spType.setSelection( when (it.bookSourceType) { + BookType.file -> 3 BookType.image -> 2 BookType.audio -> 1 else -> 0 @@ -296,6 +297,7 @@ class BookSourceEditActivity : source.enabled = binding.cbIsEnable.isChecked source.enabledExplore = binding.cbIsEnableFind.isChecked source.bookSourceType = when (binding.spType.selectedItemPosition) { + 3 -> BookType.file 2 -> BookType.image 1 -> BookType.audio else -> BookType.default diff --git a/app/src/main/res/values-es-rES/arrays.xml b/app/src/main/res/values-es-rES/arrays.xml index 345f6964a..fe92af603 100644 --- a/app/src/main/res/values-es-rES/arrays.xml +++ b/app/src/main/res/values-es-rES/arrays.xml @@ -4,6 +4,7 @@ Texto Audio Image + File diff --git a/app/src/main/res/values-pt-rBR/arrays.xml b/app/src/main/res/values-pt-rBR/arrays.xml index aaa9e60d6..4739b9d08 100644 --- a/app/src/main/res/values-pt-rBR/arrays.xml +++ b/app/src/main/res/values-pt-rBR/arrays.xml @@ -4,6 +4,7 @@ Texto Áudio Image + File diff --git a/app/src/main/res/values-zh-rHK/arrays.xml b/app/src/main/res/values-zh-rHK/arrays.xml index ca4ebc0fc..0eaf1a340 100644 --- a/app/src/main/res/values-zh-rHK/arrays.xml +++ b/app/src/main/res/values-zh-rHK/arrays.xml @@ -5,6 +5,7 @@ 文本 音頻 图片 + 文件 diff --git a/app/src/main/res/values-zh-rTW/arrays.xml b/app/src/main/res/values-zh-rTW/arrays.xml index 019b34be3..3487a326a 100644 --- a/app/src/main/res/values-zh-rTW/arrays.xml +++ b/app/src/main/res/values-zh-rTW/arrays.xml @@ -4,6 +4,7 @@ 文字 音訊 图片 + 文件 diff --git a/app/src/main/res/values-zh/arrays.xml b/app/src/main/res/values-zh/arrays.xml index 970ae369c..d44eceafb 100644 --- a/app/src/main/res/values-zh/arrays.xml +++ b/app/src/main/res/values-zh/arrays.xml @@ -4,6 +4,7 @@ 文本 音频 图片 + 文件 diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 8bc2d5232..47dd6b09a 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -4,6 +4,7 @@ Text Audio Image + File