pull/1434/head
gedoor 3 years ago
parent 85d83a2acf
commit ee25e3e777
  1. 2
      app/src/main/java/io/legado/app/help/DirectLinkUpload.kt
  2. 20
      app/src/main/java/io/legado/app/help/http/OkHttpUtils.kt
  3. 2
      app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt
  4. 33
      app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt
  5. 20
      app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceViewModel.kt
  6. 4
      app/src/main/java/io/legado/app/ui/document/HandleFileActivity.kt
  7. 15
      app/src/main/java/io/legado/app/ui/document/HandleFileViewModel.kt

@ -15,7 +15,7 @@ object DirectLinkUpload {
private const val downloadUrlRuleKey = "directLinkDownloadUrlRule" private const val downloadUrlRuleKey = "directLinkDownloadUrlRule"
private const val summaryKey = "directSummary" 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() val url = getUploadUrl()
if (url.isNullOrBlank()) { if (url.isNullOrBlank()) {
throw NoStackTraceException("上传url未配置") throw NoStackTraceException("上传url未配置")

@ -3,6 +3,7 @@ package io.legado.app.help.http
import io.legado.app.constant.AppConst import io.legado.app.constant.AppConst
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.utils.EncodingDetect import io.legado.app.utils.EncodingDetect
import io.legado.app.utils.GSON
import io.legado.app.utils.UTF8BOMFighter import io.legado.app.utils.UTF8BOMFighter
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.suspendCancellableCoroutine
@ -10,7 +11,9 @@ import kotlinx.coroutines.withContext
import okhttp3.* import okhttp3.*
import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType.Companion.toMediaType import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.asRequestBody
import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.RequestBody.Companion.toRequestBody
import java.io.File
import java.io.IOException import java.io.IOException
import java.nio.charset.Charset import java.nio.charset.Charset
import kotlin.coroutines.resume import kotlin.coroutines.resume
@ -152,9 +155,22 @@ fun Request.Builder.postMultipart(type: String?, form: Map<String, Any>) {
when (val value = it.value) { when (val value = it.value) {
is Map<*, *> -> { is Map<*, *> -> {
val fileName = value["fileName"] as String val fileName = value["fileName"] as String
val file = value["file"] as ByteArray val file = value["file"]
val mediaType = (value["contentType"] as? String)?.toMediaType() 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) multipartBody.addFormDataPart(it.key, fileName, requestBody)
} }
else -> multipartBody.addFormDataPart(it.key, it.value.toString()) else -> multipartBody.addFormDataPart(it.key, it.value.toString())

@ -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) { return getProxyClient(proxy).newCallStrResponse(retry) {
url(urlNoQuery) url(urlNoQuery)
val bodyMap = GSON.fromJsonObject<HashMap<String, Any>>(body)!! val bodyMap = GSON.fromJsonObject<HashMap<String, Any>>(body)!!

@ -9,11 +9,13 @@ import android.view.SubMenu
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.core.content.FileProvider
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.VMBaseActivity import io.legado.app.base.VMBaseActivity
import io.legado.app.constant.AppConst
import io.legado.app.constant.AppPattern import io.legado.app.constant.AppPattern
import io.legado.app.constant.EventBus import io.legado.app.constant.EventBus
import io.legado.app.data.appDb import io.legado.app.data.appDb
@ -121,8 +123,19 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
when (item.itemId) { when (item.itemId) {
R.id.menu_add_book_source -> startActivity<BookSourceEditActivity>() R.id.menu_add_book_source -> startActivity<BookSourceEditActivity>()
R.id.menu_import_qr -> qrResult.launch(null) R.id.menu_import_qr -> qrResult.launch(null)
R.id.menu_share_source -> viewModel.shareSelection(adapter.selection) { R.id.menu_share_source -> viewModel.saveToFile(adapter.selection) {
startActivity(Intent.createChooser(it, getString(R.string.share_selected_source))) 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<GroupManageDialog>() R.id.menu_group_manage -> showDialogFragment<GroupManageDialog>()
R.id.menu_import_local -> importDoc.launch { R.id.menu_import_local -> importDoc.launch {
@ -333,13 +346,15 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
R.id.menu_bottom_sel -> viewModel.bottomSource(*adapter.selection.toTypedArray()) R.id.menu_bottom_sel -> viewModel.bottomSource(*adapter.selection.toTypedArray())
R.id.menu_add_group -> selectionAddToGroups() R.id.menu_add_group -> selectionAddToGroups()
R.id.menu_remove_group -> selectionRemoveFromGroups() R.id.menu_remove_group -> selectionRemoveFromGroups()
R.id.menu_export_selection -> exportDir.launch { R.id.menu_export_selection -> viewModel.saveToFile(adapter.selection) { file ->
mode = HandleFileContract.EXPORT exportDir.launch {
fileData = Triple( mode = HandleFileContract.EXPORT
"bookSource.json", fileData = Triple(
GSON.toJson(adapter.selection).toByteArray(), "bookSource.json",
"application/json" file.readBytes(),
) "application/json"
)
}
} }
} }
return true return true

@ -1,15 +1,13 @@
package io.legado.app.ui.book.source.manage package io.legado.app.ui.book.source.manage
import android.app.Application import android.app.Application
import android.content.Intent
import android.text.TextUtils import android.text.TextUtils
import androidx.core.content.FileProvider
import io.legado.app.base.BaseViewModel import io.legado.app.base.BaseViewModel
import io.legado.app.constant.AppConst
import io.legado.app.constant.AppPattern import io.legado.app.constant.AppPattern
import io.legado.app.data.appDb import io.legado.app.data.appDb
import io.legado.app.data.entities.BookSource import io.legado.app.data.entities.BookSource
import io.legado.app.utils.* import io.legado.app.utils.*
import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
class BookSourceViewModel(application: Application) : BaseViewModel(application) { class BookSourceViewModel(application: Application) : BaseViewModel(application) {
@ -137,21 +135,15 @@ class BookSourceViewModel(application: Application) : BaseViewModel(application)
} }
@Suppress("BlockingMethodInNonBlockingContext") @Suppress("BlockingMethodInNonBlockingContext")
fun shareSelection(sources: List<BookSource>, success: ((intent: Intent) -> Unit)) { fun saveToFile(sources: List<BookSource>, success: (file: File) -> Unit) {
execute { execute {
val tmpSharePath = "${context.filesDir}/shareBookSource.json" val path = "${context.filesDir}/shareBookSource.json"
FileUtils.delete(tmpSharePath) FileUtils.delete(path)
val intent = Intent(Intent.ACTION_SEND) val file = FileUtils.createFileWithReplace(path)
val file = FileUtils.createFileWithReplace(tmpSharePath)
FileOutputStream(file).use { FileOutputStream(file).use {
GSON.writeToOutputStream(it, sources) GSON.writeToOutputStream(it, sources)
} }
val fileUri = FileProvider.getUriForFile(context, AppConst.authority, file) 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
}.onSuccess { }.onSuccess {
success.invoke(it) success.invoke(it)
}.onError { }.onError {

@ -128,10 +128,10 @@ class HandleFileActivity :
} }
} }
private fun getFileData(): Triple<String, ByteArray, String>? { private fun getFileData(): Triple<String, Any, String>? {
val fileName = intent.getStringExtra("fileName") val fileName = intent.getStringExtra("fileName")
val file = intent.getStringExtra("fileKey")?.let { val file = intent.getStringExtra("fileKey")?.let {
IntentData.get<ByteArray>(it) IntentData.get<Any>(it)
} }
val contentType = intent.getStringExtra("contentType") val contentType = intent.getStringExtra("contentType")
if (fileName != null && file != null && contentType != null) { if (fileName != null && file != null && contentType != null) {

@ -8,6 +8,7 @@ import io.legado.app.base.BaseViewModel
import io.legado.app.constant.AppLog import io.legado.app.constant.AppLog
import io.legado.app.help.DirectLinkUpload import io.legado.app.help.DirectLinkUpload
import io.legado.app.utils.FileUtils import io.legado.app.utils.FileUtils
import io.legado.app.utils.GSON
import io.legado.app.utils.isContentScheme import io.legado.app.utils.isContentScheme
import io.legado.app.utils.writeBytes import io.legado.app.utils.writeBytes
@ -20,7 +21,7 @@ class HandleFileViewModel(application: Application) : BaseViewModel(application)
fun upload( fun upload(
fileName: String, fileName: String,
file: ByteArray, file: Any,
contentType: String, contentType: String,
success: (url: String) -> Unit 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 { 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()) { return@execute if (uri.isContentScheme()) {
val doc = DocumentFile.fromTreeUri(context, uri)!! val doc = DocumentFile.fromTreeUri(context, uri)!!
doc.findFile(fileName)?.delete() doc.findFile(fileName)?.delete()
val newDoc = doc.createFile("", fileName) val newDoc = doc.createFile("", fileName)
newDoc!!.writeBytes(context, data) newDoc!!.writeBytes(context, bytes)
newDoc.uri newDoc.uri
} else { } else {
val file = File(uri.path!!) val file = File(uri.path!!)
val newFile = FileUtils.createFileIfNotExist(file, fileName) val newFile = FileUtils.createFileIfNotExist(file, fileName)
newFile.writeBytes(data) newFile.writeBytes(bytes)
Uri.fromFile(newFile) Uri.fromFile(newFile)
} }
}.onError { }.onError {

Loading…
Cancel
Save