Merge pull request #1874 from Xwite/master

refactor:在线书籍文件导入
pull/1876/head^2
kunfei 3 years ago committed by GitHub
commit 425e20b2bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      app/src/main/assets/web/bookSource/index.html
  2. 44
      app/src/main/java/io/legado/app/api/controller/BookController.kt
  3. 3
      app/src/main/java/io/legado/app/constant/BookType.kt
  4. 2
      app/src/main/java/io/legado/app/data/entities/BookSource.kt
  5. 14
      app/src/main/java/io/legado/app/help/JsExtensions.kt
  6. 61
      app/src/main/java/io/legado/app/model/localBook/LocalBook.kt
  7. 2
      app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt
  8. 1
      app/src/main/res/values-es-rES/arrays.xml
  9. 1
      app/src/main/res/values-pt-rBR/arrays.xml
  10. 1
      app/src/main/res/values-zh-rHK/arrays.xml
  11. 1
      app/src/main/res/values-zh-rTW/arrays.xml
  12. 1
      app/src/main/res/values-zh/arrays.xml
  13. 1
      app/src/main/res/values/arrays.xml

@ -25,7 +25,7 @@
<div> <div>
<div>源类型 :</div> <div>源类型 :</div>
<textarea rows="1" id="bookSourceType" class="base" title="bookSourceType" <textarea rows="1" id="bookSourceType" class="base" title="bookSourceType"
placeholder="&lt;必填&gt;0:文本 1:音频 2:图片"></textarea> placeholder="&lt;必填&gt;0:文本 1:音频 2:图片 3:文件(只提供下载的网站)"></textarea>
</div> </div>
<div> <div>
<div>源名称 :</div> <div>源名称 :</div>

@ -1,9 +1,7 @@
package io.legado.app.api.controller package io.legado.app.api.controller
import android.net.Uri import android.net.Uri
import android.util.Base64
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import androidx.documentfile.provider.DocumentFile
import io.legado.app.api.ReturnData import io.legado.app.api.ReturnData
import io.legado.app.constant.PreferKey import io.legado.app.constant.PreferKey
import io.legado.app.data.appDb 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.BookHelp
import io.legado.app.help.CacheManager import io.legado.app.help.CacheManager
import io.legado.app.help.ContentProcessor 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.glide.ImageLoader
import io.legado.app.help.storage.AppWebDav import io.legado.app.help.storage.AppWebDav
import io.legado.app.model.BookCover import io.legado.app.model.BookCover
@ -27,7 +24,6 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import splitties.init.appCtx import splitties.init.appCtx
import java.io.File import java.io.File
import java.io.FileOutputStream
object BookController { object BookController {
@ -248,45 +244,7 @@ object BookController {
val fileData = parameters["fileData"]?.firstOrNull() val fileData = parameters["fileData"]?.firstOrNull()
?: return returnData.setErrorMsg("fileData 不能为空") ?: return returnData.setErrorMsg("fileData 不能为空")
kotlin.runCatching { kotlin.runCatching {
val defaultBookTreeUri = AppConfig.defaultBookTreeUri LocalBook.importFile(fileData, fileName)
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)
}.onFailure { }.onFailure {
return when (it) { return when (it) {
is SecurityException -> returnData.setErrorMsg("需重新设置书籍保存位置!") is SecurityException -> returnData.setErrorMsg("需重新设置书籍保存位置!")

@ -5,7 +5,8 @@ import androidx.annotation.IntDef
object BookType { object BookType {
const val default = 0 // 0 文本 const val default = 0 // 0 文本
const val audio = 1 // 1 音频 const val audio = 1 // 1 音频
const val image = 2 //图片 const val image = 2 // 2 图片
const val file = 3 // 3 只提供下载服务的网站
const val local = "loc_book" const val local = "loc_book"
@Target(AnnotationTarget.VALUE_PARAMETER) @Target(AnnotationTarget.VALUE_PARAMETER)

@ -27,7 +27,7 @@ data class BookSource(
var bookSourceName: String = "", var bookSourceName: String = "",
// 分组 // 分组
var bookSourceGroup: String? = null, var bookSourceGroup: String? = null,
// 类型,0 文本,1 音频, 2 图片 // 类型,0 文本,1 音频, 2 图片, 3 文件(指的是类似知轩藏书只提供下载的网站)
@BookType.Type @BookType.Type
var bookSourceType: Int = 0, var bookSourceType: Int = 0,
// 详情页url正则 // 详情页url正则

@ -197,12 +197,10 @@ interface JsExtensions {
*js实现读取cookie *js实现读取cookie
*/ */
fun getCookie(tag: String, key: String? = null): String { fun getCookie(tag: String, key: String? = null): String {
val cookie = CookieStore.getCookie(tag)
val cookieMap = CookieStore.cookieToMap(cookie)
return if (key != null) { return if (key != null) {
cookieMap[key] ?: "" CookieStore.getKey(tag, key)
} else { } else {
cookie CookieStore.getCookie(tag)
} }
} }
@ -470,10 +468,8 @@ interface JsExtensions {
* @return zip指定文件的数据 * @return zip指定文件的数据
*/ */
fun getZipByteArrayContent(url: String, path: String): ByteArray? { fun getZipByteArrayContent(url: String, path: String): ByteArray? {
val bytes = if (url.startsWith("http://") || url.startsWith("https://")) { val bytes = if (url.isAbsUrl()) {
runBlocking { AnalyzeUrl(url, source = getSource()).getByteArray()
return@runBlocking okHttpClient.newCallResponseBody { url(url) }.bytes()
}
} else { } else {
StringUtils.hexStringToByte(url) StringUtils.hexStringToByte(url)
} }
@ -517,7 +513,7 @@ interface JsExtensions {
str.isAbsUrl() -> runBlocking { str.isAbsUrl() -> runBlocking {
var x = CacheManager.getByteArray(key) var x = CacheManager.getByteArray(key)
if (x == null) { if (x == null) {
x = okHttpClient.newCallResponseBody { url(str) }.bytes() x = AnalyzeUrl(str, source = getSource()).getByteArray()
x.let { x.let {
CacheManager.put(key, it) CacheManager.put(key, it)
} }

@ -1,6 +1,7 @@
package io.legado.app.model.localBook package io.legado.app.model.localBook
import android.net.Uri import android.net.Uri
import android.util.Base64
import androidx.documentfile.provider.DocumentFile import androidx.documentfile.provider.DocumentFile
import com.script.SimpleBindings import com.script.SimpleBindings
import io.legado.app.R 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.appDb
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.data.entities.BaseSource
import io.legado.app.exception.TocEmptyException import io.legado.app.exception.TocEmptyException
import io.legado.app.exception.NoStackTraceException
import io.legado.app.help.BookHelp import io.legado.app.help.BookHelp
import io.legado.app.help.config.AppConfig import io.legado.app.help.config.AppConfig
import io.legado.app.model.analyzeRule.AnalyzeUrl
import io.legado.app.utils.* import io.legado.app.utils.*
import splitties.init.appCtx import splitties.init.appCtx
import java.io.File import java.io.File
import java.io.FileInputStream import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.FileNotFoundException import java.io.FileNotFoundException
import java.io.InputStream import java.io.InputStream
import java.util.regex.Pattern 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 { fun importFile(uri: Uri): Book {
val bookUrl: String val bookUrl: String
val updateTime: Long val updateTime: Long
@ -119,7 +150,7 @@ object LocalBook {
return book return book
} }
fun analyzeNameAuthor(fileName: String): Pair<String, String> { private fun analyzeNameAuthor(fileName: String): Pair<String, String> {
val tempFileName = fileName.substringBeforeLast(".") val tempFileName = fileName.substringBeforeLast(".")
var name: String var name: String
var author: 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)
}
}
} }

@ -192,6 +192,7 @@ class BookSourceEditActivity :
binding.cbIsEnableFind.isChecked = it.enabledExplore binding.cbIsEnableFind.isChecked = it.enabledExplore
binding.spType.setSelection( binding.spType.setSelection(
when (it.bookSourceType) { when (it.bookSourceType) {
BookType.file -> 3
BookType.image -> 2 BookType.image -> 2
BookType.audio -> 1 BookType.audio -> 1
else -> 0 else -> 0
@ -296,6 +297,7 @@ class BookSourceEditActivity :
source.enabled = binding.cbIsEnable.isChecked source.enabled = binding.cbIsEnable.isChecked
source.enabledExplore = binding.cbIsEnableFind.isChecked source.enabledExplore = binding.cbIsEnableFind.isChecked
source.bookSourceType = when (binding.spType.selectedItemPosition) { source.bookSourceType = when (binding.spType.selectedItemPosition) {
3 -> BookType.file
2 -> BookType.image 2 -> BookType.image
1 -> BookType.audio 1 -> BookType.audio
else -> BookType.default else -> BookType.default

@ -4,6 +4,7 @@
<item>Texto</item> <item>Texto</item>
<item>Audio</item> <item>Audio</item>
<item>Image</item> <item>Image</item>
<item>File</item>
</string-array> </string-array>
<string-array name="group_style"> <string-array name="group_style">

@ -4,6 +4,7 @@
<item>Texto</item> <item>Texto</item>
<item>Áudio</item> <item>Áudio</item>
<item>Image</item> <item>Image</item>
<item>File</item>
</string-array> </string-array>
<string-array name="group_style"> <string-array name="group_style">

@ -5,6 +5,7 @@
<item>文本</item> <item>文本</item>
<item>音頻</item> <item>音頻</item>
<item>图片</item> <item>图片</item>
<item>文件</item>
</string-array> </string-array>
<string-array name="group_style"> <string-array name="group_style">

@ -4,6 +4,7 @@
<item>文字</item> <item>文字</item>
<item>音訊</item> <item>音訊</item>
<item>图片</item> <item>图片</item>
<item>文件</item>
</string-array> </string-array>
<string-array name="group_style"> <string-array name="group_style">

@ -4,6 +4,7 @@
<item>文本</item> <item>文本</item>
<item>音频</item> <item>音频</item>
<item>图片</item> <item>图片</item>
<item>文件</item>
</string-array> </string-array>
<string-array name="group_style"> <string-array name="group_style">

@ -4,6 +4,7 @@
<item>Text</item> <item>Text</item>
<item>Audio</item> <item>Audio</item>
<item>Image</item> <item>Image</item>
<item>File</item>
</string-array> </string-array>
<string-array name="group_style"> <string-array name="group_style">

Loading…
Cancel
Save