From 441f6962946798363cd4c74efa77c7b511c0c788 Mon Sep 17 00:00:00 2001 From: Horis <821938089@qq.com> Date: Fri, 28 Oct 2022 09:12:31 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/io/legado/app/help/AppWebDav.kt | 16 +++++++++ .../java/io/legado/app/lib/webdav/WebDav.kt | 22 ++++++++++++ .../app/ui/book/cache/CacheViewModel.kt | 35 +++++++++---------- .../java/io/legado/app/utils/UriExtensions.kt | 23 ++++++++++++ 4 files changed, 77 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/io/legado/app/help/AppWebDav.kt b/app/src/main/java/io/legado/app/help/AppWebDav.kt index c797911a5..7b0ffe3b7 100644 --- a/app/src/main/java/io/legado/app/help/AppWebDav.kt +++ b/app/src/main/java/io/legado/app/help/AppWebDav.kt @@ -1,6 +1,7 @@ package io.legado.app.help import android.content.Context +import android.net.Uri import io.legado.app.R import io.legado.app.constant.AppLog import io.legado.app.constant.PreferKey @@ -207,6 +208,21 @@ object AppWebDav { } } + suspend fun exportWebDav(uri: Uri, fileName: String) { + if (!NetworkUtils.isAvailable()) return + try { + authorization?.let { + // 如果导出的本地文件存在,开始上传 + val putUrl = exportsWebDavUrl + fileName + WebDav(putUrl, it).upload(uri, "text/plain") + } + } catch (e: Exception) { + val msg = "WebDav导出\n${e.localizedMessage}" + AppLog.put(msg, e) + appCtx.toastOnUi(msg) + } + } + fun uploadBookProgress(book: Book) { val authorization = authorization ?: return if (!syncBookProgress) return diff --git a/app/src/main/java/io/legado/app/lib/webdav/WebDav.kt b/app/src/main/java/io/legado/app/lib/webdav/WebDav.kt index 8ceeafe93..ccaa7e0c6 100644 --- a/app/src/main/java/io/legado/app/lib/webdav/WebDav.kt +++ b/app/src/main/java/io/legado/app/lib/webdav/WebDav.kt @@ -1,6 +1,7 @@ package io.legado.app.lib.webdav import android.annotation.SuppressLint +import android.net.Uri import io.legado.app.constant.AppLog import io.legado.app.exception.NoStackTraceException import io.legado.app.help.http.newCallResponse @@ -8,6 +9,7 @@ import io.legado.app.help.http.okHttpClient import io.legado.app.help.http.text import io.legado.app.utils.NetworkUtils import io.legado.app.utils.printOnDebug +import io.legado.app.utils.toRequestBody import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.withContext import okhttp3.Interceptor @@ -316,6 +318,26 @@ open class WebDav(val path: String, val authorization: Authorization) { } } + @Throws(WebDavException::class) + suspend fun upload(uri: Uri, contentType: String) { + // 务必注意RequestBody不要嵌套,不然上传时内容可能会被追加多余的文件信息 + kotlin.runCatching { + withContext(IO) { + val fileBody = uri.toRequestBody(contentType.toMediaType()) + val url = httpUrl ?: throw NoStackTraceException("url不能为空") + webDavClient.newCallResponse { + url(url) + put(fileBody) + }.let { + checkResult(it) + } + } + }.onFailure { + AppLog.put("WebDav上传失败\n${it.localizedMessage}", it) + throw WebDavException("WebDav上传失败\n${it.localizedMessage}") + } + } + @Throws(WebDavException::class) suspend fun downloadInputStream(): InputStream { val url = httpUrl ?: throw WebDavException("WebDav下载出错\nurl为空") diff --git a/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt b/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt index f26e96a4b..89e124ba8 100644 --- a/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt @@ -122,7 +122,9 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { exportMsg[book.bookUrl] = context.getString(R.string.export_success) upAdapterLiveData.postValue(book.bookUrl) }.onFinally { - exportNumber-- + mutex.withLock { + exportNumber-- + } } } @@ -132,14 +134,9 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { DocumentUtils.delete(doc, filename) val bookDoc = DocumentUtils.createFileIfNotExist(doc, filename) ?: throw NoStackTraceException("创建文档失败,请尝试重新设置导出文件夹") - val stringBuilder = StringBuilder() - val exportToWebDav = AppConfig.exportToWebDav context.contentResolver.openOutputStream(bookDoc.uri, "wa")?.use { bookOs -> getAllContents(book) { text, srcList -> bookOs.write(text.toByteArray(Charset.forName(AppConfig.exportCharset))) - if (exportToWebDav) { - stringBuilder.append(text) - } srcList?.forEach { val vFile = BookHelp.getImage(book, it.third) if (vFile.exists()) { @@ -154,9 +151,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { } if (AppConfig.exportToWebDav) { // 导出到webdav - val byteArray = - stringBuilder.toString().toByteArray(Charset.forName(AppConfig.exportCharset)) - AppWebDav.exportWebDav(byteArray, filename) + AppWebDav.exportWebDav(bookDoc.uri, filename) } } @@ -164,13 +159,8 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { val filename = "${getExportFileName(book)}.txt" val bookPath = FileUtils.getPath(file, filename) val bookFile = FileUtils.createFileWithReplace(bookPath) - val stringBuilder = StringBuilder() - val exportToWebDav = AppConfig.exportToWebDav getAllContents(book) { text, srcList -> bookFile.appendText(text, Charset.forName(AppConfig.exportCharset)) - if (exportToWebDav) { - stringBuilder.append(text) - } srcList?.forEach { val vFile = BookHelp.getImage(book, it.third) if (vFile.exists()) { @@ -185,9 +175,7 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { } } if (AppConfig.exportToWebDav) { - val byteArray = - stringBuilder.toString().toByteArray(Charset.forName(AppConfig.exportCharset)) - AppWebDav.exportWebDav(byteArray, filename) // 导出到webdav + AppWebDav.exportWebDav(Uri.fromFile(bookFile), filename) // 导出到webdav } } @@ -299,7 +287,9 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { exportMsg[book.bookUrl] = context.getString(R.string.export_success) upAdapterLiveData.postValue(book.bookUrl) }.onFinally { - exportNumber-- + mutex.withLock { + exportNumber-- + } } } @@ -322,7 +312,10 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { context.contentResolver.openOutputStream(bookDoc.uri, "wa")?.use { bookOs -> EpubWriter().write(epubBook, bookOs) } - + if (AppConfig.exportToWebDav) { + // 导出到webdav + AppWebDav.exportWebDav(bookDoc.uri, filename) + } } } @@ -344,6 +337,10 @@ class CacheViewModel(application: Application) : BaseViewModel(application) { setEpubContent(contentModel, book, epubBook) @Suppress("BlockingMethodInNonBlockingContext") EpubWriter().write(epubBook, FileOutputStream(bookFile)) + if (AppConfig.exportToWebDav) { + // 导出到webdav + AppWebDav.exportWebDav(Uri.fromFile(bookFile), filename) + } } private fun setAssets(doc: DocumentFile, book: Book, epubBook: EpubBook): String { diff --git a/app/src/main/java/io/legado/app/utils/UriExtensions.kt b/app/src/main/java/io/legado/app/utils/UriExtensions.kt index 7f9b19bd4..26a62715a 100644 --- a/app/src/main/java/io/legado/app/utils/UriExtensions.kt +++ b/app/src/main/java/io/legado/app/utils/UriExtensions.kt @@ -10,6 +10,11 @@ import io.legado.app.constant.AppLog import io.legado.app.exception.NoStackTraceException import io.legado.app.lib.permission.Permissions import io.legado.app.lib.permission.PermissionsCompat +import okhttp3.MediaType +import okhttp3.RequestBody +import okio.BufferedSink +import okio.source +import splitties.init.appCtx import java.io.File import java.io.FileInputStream import java.io.InputStream @@ -197,4 +202,22 @@ fun Uri.inputStream(context: Context): Result { throw e } } +} + +fun Uri.toRequestBody(contentType: MediaType? = null): RequestBody { + val uri = this + return object : RequestBody() { + override fun contentType() = contentType + + override fun contentLength(): Long { + val length = uri.inputStream(appCtx).getOrThrow().available().toLong() + return if (length > 0) length else -1 + } + + override fun writeTo(sink: BufferedSink) { + uri.inputStream(appCtx).getOrThrow().source().use { source -> + sink.writeAll(source) + } + } + } } \ No newline at end of file