|
|
@ -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) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|