diff --git a/app/src/main/java/io/legado/app/help/DirectLinkUpload.kt b/app/src/main/java/io/legado/app/help/DirectLinkUpload.kt index f2427a301..fcceecfd6 100644 --- a/app/src/main/java/io/legado/app/help/DirectLinkUpload.kt +++ b/app/src/main/java/io/legado/app/help/DirectLinkUpload.kt @@ -15,7 +15,7 @@ object DirectLinkUpload { private const val downloadUrlRuleKey = "directLinkDownloadUrlRule" private const val summaryKey = "directSummary" - suspend fun upLoad(fileName: String, file: ByteArray, contentType: String): String { + suspend fun upLoad(fileName: String, file: Any, contentType: String): String { val url = getUploadUrl() if (url.isNullOrBlank()) { throw NoStackTraceException("上传url未配置") diff --git a/app/src/main/java/io/legado/app/help/http/OkHttpUtils.kt b/app/src/main/java/io/legado/app/help/http/OkHttpUtils.kt index e3774b3f1..c92d93945 100644 --- a/app/src/main/java/io/legado/app/help/http/OkHttpUtils.kt +++ b/app/src/main/java/io/legado/app/help/http/OkHttpUtils.kt @@ -3,6 +3,7 @@ package io.legado.app.help.http import io.legado.app.constant.AppConst import io.legado.app.help.AppConfig import io.legado.app.utils.EncodingDetect +import io.legado.app.utils.GSON import io.legado.app.utils.UTF8BOMFighter import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.suspendCancellableCoroutine @@ -10,7 +11,9 @@ import kotlinx.coroutines.withContext import okhttp3.* import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.MediaType.Companion.toMediaType +import okhttp3.RequestBody.Companion.asRequestBody import okhttp3.RequestBody.Companion.toRequestBody +import java.io.File import java.io.IOException import java.nio.charset.Charset import kotlin.coroutines.resume @@ -152,9 +155,22 @@ fun Request.Builder.postMultipart(type: String?, form: Map) { when (val value = it.value) { is Map<*, *> -> { val fileName = value["fileName"] as String - val file = value["file"] as ByteArray + val file = value["file"] val mediaType = (value["contentType"] as? String)?.toMediaType() - val requestBody = file.toRequestBody(mediaType) + val requestBody = when (file) { + is File -> { + file.asRequestBody(mediaType) + } + is ByteArray -> { + file.toRequestBody(mediaType) + } + is String -> { + file.toRequestBody(mediaType) + } + else -> { + GSON.toJson(file).toRequestBody(mediaType) + } + } multipartBody.addFormDataPart(it.key, fileName, requestBody) } else -> multipartBody.addFormDataPart(it.key, it.value.toString()) diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt index cd0d02fcd..81b11e51b 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt @@ -481,7 +481,7 @@ class AnalyzeUrl( /** * 上传文件 */ - suspend fun upload(fileName: String, file: ByteArray, contentType: String): StrResponse { + suspend fun upload(fileName: String, file: Any, contentType: String): StrResponse { return getProxyClient(proxy).newCallStrResponse(retry) { url(urlNoQuery) val bodyMap = GSON.fromJsonObject>(body)!! diff --git a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt index 1383de194..aa21d2cbf 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt @@ -9,11 +9,13 @@ import android.view.SubMenu import androidx.activity.viewModels import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.SearchView +import androidx.core.content.FileProvider import androidx.core.os.bundleOf import androidx.recyclerview.widget.ItemTouchHelper import com.google.android.material.snackbar.Snackbar import io.legado.app.R import io.legado.app.base.VMBaseActivity +import io.legado.app.constant.AppConst import io.legado.app.constant.AppPattern import io.legado.app.constant.EventBus import io.legado.app.data.appDb @@ -121,8 +123,19 @@ class BookSourceActivity : VMBaseActivity startActivity() R.id.menu_import_qr -> qrResult.launch(null) - R.id.menu_share_source -> viewModel.shareSelection(adapter.selection) { - startActivity(Intent.createChooser(it, getString(R.string.share_selected_source))) + R.id.menu_share_source -> viewModel.saveToFile(adapter.selection) { + val fileUri = FileProvider.getUriForFile(this, AppConst.authority, it) + val intent = Intent(Intent.ACTION_SEND) + intent.type = "text/*" + intent.putExtra(Intent.EXTRA_STREAM, fileUri) + intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + startActivity( + Intent.createChooser( + intent, + getString(R.string.share_selected_source) + ) + ) } R.id.menu_group_manage -> showDialogFragment() R.id.menu_import_local -> importDoc.launch { @@ -333,13 +346,15 @@ class BookSourceActivity : VMBaseActivity viewModel.bottomSource(*adapter.selection.toTypedArray()) R.id.menu_add_group -> selectionAddToGroups() R.id.menu_remove_group -> selectionRemoveFromGroups() - R.id.menu_export_selection -> exportDir.launch { - mode = HandleFileContract.EXPORT - fileData = Triple( - "bookSource.json", - GSON.toJson(adapter.selection).toByteArray(), - "application/json" - ) + R.id.menu_export_selection -> viewModel.saveToFile(adapter.selection) { file -> + exportDir.launch { + mode = HandleFileContract.EXPORT + fileData = Triple( + "bookSource.json", + file.readBytes(), + "application/json" + ) + } } } return true diff --git a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceViewModel.kt b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceViewModel.kt index 11d678a8f..dee06807a 100644 --- a/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceViewModel.kt @@ -1,15 +1,13 @@ package io.legado.app.ui.book.source.manage import android.app.Application -import android.content.Intent import android.text.TextUtils -import androidx.core.content.FileProvider import io.legado.app.base.BaseViewModel -import io.legado.app.constant.AppConst import io.legado.app.constant.AppPattern import io.legado.app.data.appDb import io.legado.app.data.entities.BookSource import io.legado.app.utils.* +import java.io.File import java.io.FileOutputStream class BookSourceViewModel(application: Application) : BaseViewModel(application) { @@ -137,21 +135,15 @@ class BookSourceViewModel(application: Application) : BaseViewModel(application) } @Suppress("BlockingMethodInNonBlockingContext") - fun shareSelection(sources: List, success: ((intent: Intent) -> Unit)) { + fun saveToFile(sources: List, success: (file: File) -> Unit) { execute { - val tmpSharePath = "${context.filesDir}/shareBookSource.json" - FileUtils.delete(tmpSharePath) - val intent = Intent(Intent.ACTION_SEND) - val file = FileUtils.createFileWithReplace(tmpSharePath) + val path = "${context.filesDir}/shareBookSource.json" + FileUtils.delete(path) + val file = FileUtils.createFileWithReplace(path) FileOutputStream(file).use { GSON.writeToOutputStream(it, sources) } - val fileUri = FileProvider.getUriForFile(context, AppConst.authority, file) - intent.type = "text/*" - intent.putExtra(Intent.EXTRA_STREAM, fileUri) - intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - intent + file }.onSuccess { success.invoke(it) }.onError { diff --git a/app/src/main/java/io/legado/app/ui/document/HandleFileActivity.kt b/app/src/main/java/io/legado/app/ui/document/HandleFileActivity.kt index 10916635a..dad9157b2 100644 --- a/app/src/main/java/io/legado/app/ui/document/HandleFileActivity.kt +++ b/app/src/main/java/io/legado/app/ui/document/HandleFileActivity.kt @@ -128,10 +128,10 @@ class HandleFileActivity : } } - private fun getFileData(): Triple? { + private fun getFileData(): Triple? { val fileName = intent.getStringExtra("fileName") val file = intent.getStringExtra("fileKey")?.let { - IntentData.get(it) + IntentData.get(it) } val contentType = intent.getStringExtra("contentType") if (fileName != null && file != null && contentType != null) { diff --git a/app/src/main/java/io/legado/app/ui/document/HandleFileViewModel.kt b/app/src/main/java/io/legado/app/ui/document/HandleFileViewModel.kt index 14cf13334..b82bedd2a 100644 --- a/app/src/main/java/io/legado/app/ui/document/HandleFileViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/document/HandleFileViewModel.kt @@ -8,6 +8,7 @@ import io.legado.app.base.BaseViewModel import io.legado.app.constant.AppLog import io.legado.app.help.DirectLinkUpload import io.legado.app.utils.FileUtils +import io.legado.app.utils.GSON import io.legado.app.utils.isContentScheme import io.legado.app.utils.writeBytes @@ -20,7 +21,7 @@ class HandleFileViewModel(application: Application) : BaseViewModel(application) fun upload( fileName: String, - file: ByteArray, + file: Any, contentType: String, success: (url: String) -> Unit ) { @@ -35,18 +36,24 @@ class HandleFileViewModel(application: Application) : BaseViewModel(application) } } - fun saveToLocal(uri: Uri, fileName: String, data: ByteArray, success: (uri: Uri) -> Unit) { + fun saveToLocal(uri: Uri, fileName: String, data: Any, success: (uri: Uri) -> Unit) { execute { + val bytes = when (data) { + is File -> data.readBytes() + is ByteArray -> data + is String -> data.toByteArray() + else -> GSON.toJson(data).toByteArray() + } return@execute if (uri.isContentScheme()) { val doc = DocumentFile.fromTreeUri(context, uri)!! doc.findFile(fileName)?.delete() val newDoc = doc.createFile("", fileName) - newDoc!!.writeBytes(context, data) + newDoc!!.writeBytes(context, bytes) newDoc.uri } else { val file = File(uri.path!!) val newFile = FileUtils.createFileIfNotExist(file, fileName) - newFile.writeBytes(data) + newFile.writeBytes(bytes) Uri.fromFile(newFile) } }.onError {