Przeglądaj źródła

保存书籍要分两种情况判断

kunfei 4 lat temu
rodzic
commit
cf5501ecae

+ 40 - 19
app/src/main/java/io/legado/app/api/controller/BookController.kt

@@ -1,8 +1,9 @@
 package io.legado.app.api.controller
 
+import android.net.Uri
 import android.util.Base64
 import androidx.core.graphics.drawable.toBitmap
-import io.legado.app.R
+import androidx.documentfile.provider.DocumentFile
 import io.legado.app.api.ReturnData
 import io.legado.app.constant.PreferKey
 import io.legado.app.data.appDb
@@ -22,7 +23,8 @@ import io.legado.app.model.webBook.WebBook
 import io.legado.app.utils.*
 import kotlinx.coroutines.runBlocking
 import splitties.init.appCtx
-import timber.log.Timber
+import java.io.File
+import java.io.FileOutputStream
 
 object BookController {
 
@@ -202,36 +204,55 @@ object BookController {
      */
     fun addLocalBook(parameters: Map<String, List<String>>): ReturnData {
         val returnData = ReturnData()
-        try {
-            val fileName = parameters["fileName"]?.firstOrNull()
-                ?: return returnData.setErrorMsg("fileName 不能为空")
-            val fileData = parameters["fileData"]?.firstOrNull()
-                ?: return returnData.setErrorMsg("fileData 不能为空")
-            if (AppConfig.defaultBookTreeUri == null) return returnData.setErrorMsg("没有设置书籍保存位置!")
-            val bookFolder = FileUtils.createFolderIfNotExist(AppConfig.defaultBookTreeUri!!)
-            val file = FileUtils.createFileIfNotExist(bookFolder, fileName)
-            val fileBytes = Base64.decode(fileData.substringAfter("base64,"), Base64.DEFAULT)
-            file.writeBytes(fileBytes)
+        val fileName = parameters["fileName"]?.firstOrNull()
+            ?: return returnData.setErrorMsg("fileName 不能为空")
+        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 = file.absolutePath,
+                bookUrl = uri.toString(),
                 name = nameAuthor.first,
                 author = nameAuthor.second,
                 originName = fileName,
                 coverUrl = FileUtils.getPath(
                     appCtx.externalFiles,
                     "covers",
-                    "${MD5Utils.md5Encode16(file.absolutePath)}.jpg"
+                    "${MD5Utils.md5Encode16(uri.toString())}.jpg"
                 )
             )
             if (book.isEpub()) EpubFile.upBookInfo(book)
             if (book.isUmd()) UmdFile.upBookInfo(book)
             appDb.bookDao.insert(book)
-        } catch (e: Exception) {
-            Timber.e(e)
-            return returnData.setErrorMsg(
-                e.localizedMessage ?: appCtx.getString(R.string.unknown_error)
-            )
+        }.onFailure {
+            return when (it) {
+                is SecurityException -> returnData.setErrorMsg("需重新设置书籍保存位置!")
+                else -> returnData.setErrorMsg("保存书籍错误\n${it.localizedMessage}")
+            }
         }
         return returnData.setData(true)
     }