完善代码

This commit is contained in:
aoi
2026-05-22 01:55:38 +08:00
committed by Kudomaga
parent c7b38ab800
commit 43b401c52b
4 changed files with 54 additions and 44 deletions
@@ -14,6 +14,7 @@ import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.server.websocket.*
import io.ktor.util.pipeline.*
import io.ktor.util.toMap
import io.legado.app.api.ReturnData
import io.legado.app.api.controller.BookController
import io.legado.app.api.controller.BookSourceController
@@ -29,7 +30,9 @@ import io.legado.app.web.socket.RssSourceDebugWebSocket
import io.legado.app.web.utils.AssetsWeb
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import splitties.init.appCtx
import java.io.ByteArrayOutputStream
import java.io.File
class KtorServer(private val port: Int) {
private var server: ApplicationEngine? = null
@@ -62,32 +65,46 @@ class KtorServer(private val port: Int) {
WebService.serve()
val multipart = call.receiveMultipart()
var fileName: String? = null
var fileBytes: ByteArray? = null
multipart.forEachPart { part ->
when (part) {
is PartData.FormItem -> {
if (part.name == "fileName") fileName = part.value
val tempFile = File(appCtx.cacheDir, "upload_${System.currentTimeMillis()}")
try {
multipart.forEachPart { part ->
when (part) {
is PartData.FormItem -> {
if (part.name == "fileName") fileName = part.value
}
is PartData.FileItem -> {
part.streamProvider().use { input ->
tempFile.outputStream().use { output ->
input.copyTo(output)
}
}
if (fileName == null) {
fileName = part.originalFileName
}
}
else -> {}
}
is PartData.FileItem -> {
fileBytes = part.streamProvider().readBytes()
}
else -> {}
part.dispose()
}
part.dispose()
}
if (fileName != null && fileBytes != null) {
val returnData = withContext(Dispatchers.IO) {
kotlin.runCatching {
val uri = LocalBook.saveBookFile(fileBytes!!.inputStream(), fileName!!)
LocalBook.importFile(uri)
ReturnData().setData(true)
}.getOrElse {
ReturnData().setErrorMsg(it.localizedMessage ?: "Save book error")
if (fileName != null && tempFile.exists()) {
val returnData = withContext(Dispatchers.IO) {
kotlin.runCatching {
tempFile.inputStream().use {
val uri = LocalBook.saveBookFile(it, fileName!!)
LocalBook.importFile(uri)
ReturnData().setData(true)
}
}.getOrElse {
LogUtils.e(TAG, it.stackTraceStr)
ReturnData().setErrorMsg(it.localizedMessage ?: "Save book error")
}
}
respondReturnData(returnData)
} else {
call.respond(HttpStatusCode.BadRequest, "Missing fileName or fileData")
}
respondReturnData(returnData)
} else {
call.respond(HttpStatusCode.BadRequest, "Missing fileName or fileData")
} finally {
if (tempFile.exists()) tempFile.delete()
}
}
post("/saveReadConfig") { handlePost { BookController.saveWebReadConfig(it) } }
@@ -113,12 +130,14 @@ class KtorServer(private val port: Int) {
get("{...}") {
WebService.serve()
var uri = call.request.uri.substringBefore("?")
var uri = call.request.path()
if (uri.endsWith("/")) uri += "index.html"
val inputStream = assetsWeb.getInputStream(uri)
if (inputStream != null) {
call.respondOutputStream(ContentType.parse(assetsWeb.getMimeType(uri))) {
inputStream.copyTo(this)
inputStream.use { stream ->
call.respondOutputStream(ContentType.parse(assetsWeb.getMimeType(uri))) {
stream.copyTo(this)
}
}
} else {
call.respond(HttpStatusCode.NotFound)
@@ -195,12 +214,6 @@ class KtorServer(private val port: Int) {
}
}
private fun Parameters.toMap(): Map<String, List<String>> {
val map = mutableMapOf<String, List<String>>()
this.forEach { s, list -> map[s] = list }
return map
}
companion object {
private const val TAG = "KtorServer"
}
@@ -13,7 +13,6 @@ import io.legado.app.help.config.AppConfig
import io.legado.app.ui.config.otherConfig.OtherConfig
import io.legado.app.utils.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.consumeEach
import org.koin.core.context.GlobalContext
import splitties.init.appCtx
@@ -28,13 +27,13 @@ class BookSearchWebSocket(private val session: DefaultWebSocketServerSession) :
suspend fun handle() {
try {
session.incoming.consumeEach { frame ->
for (frame in session.incoming) {
if (frame is Frame.Text) {
val text = frame.readText()
if (!text.isJson()) {
session.send("数据必须为Json格式")
session.close(CloseReason(CloseReason.Codes.NORMAL, SEARCH_FINISH))
return@consumeEach
break
}
val searchMap = GSON.fromJsonObject<Map<String, String>>(text).getOrNull()
if (searchMap != null) {
@@ -42,7 +41,7 @@ class BookSearchWebSocket(private val session: DefaultWebSocketServerSession) :
if (key.isNullOrBlank()) {
session.send(appCtx.getString(R.string.cannot_empty))
session.close(CloseReason(CloseReason.Codes.NORMAL, SEARCH_FINISH))
return@consumeEach
break
}
startSearch(key)
}
@@ -7,7 +7,6 @@ import io.legado.app.data.appDb
import io.legado.app.model.Debug
import io.legado.app.utils.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.consumeEach
import splitties.init.appCtx
/**
@@ -21,13 +20,13 @@ class BookSourceDebugWebSocket(private val session: DefaultWebSocketServerSessio
suspend fun handle() {
try {
session.incoming.consumeEach { frame ->
for (frame in session.incoming) {
if (frame is Frame.Text) {
val text = frame.readText()
if (!text.isJson()) {
session.send("数据必须为Json格式")
session.close(CloseReason(CloseReason.Codes.NORMAL, "调试结束"))
return@consumeEach
break
}
val debugBean = GSON.fromJsonObject<Map<String, String>>(text).getOrNull()
if (debugBean != null) {
@@ -36,7 +35,7 @@ class BookSourceDebugWebSocket(private val session: DefaultWebSocketServerSessio
if (tag.isNullOrBlank() || key.isNullOrBlank()) {
session.send(appCtx.getString(R.string.cannot_empty))
session.close(CloseReason(CloseReason.Codes.NORMAL, "调试结束"))
return@consumeEach
break
}
appDb.bookSourceDao.getBookSource(tag)?.let {
Debug.callback = this@BookSourceDebugWebSocket
@@ -45,7 +44,7 @@ class BookSourceDebugWebSocket(private val session: DefaultWebSocketServerSessio
} else {
session.send("数据必须为Json格式")
session.close(CloseReason(CloseReason.Codes.NORMAL, "调试结束"))
return@consumeEach
break
}
}
}
@@ -7,7 +7,6 @@ import io.legado.app.data.appDb
import io.legado.app.model.Debug
import io.legado.app.utils.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.consumeEach
import splitties.init.appCtx
/**
@@ -21,13 +20,13 @@ class RssSourceDebugWebSocket(private val session: DefaultWebSocketServerSession
suspend fun handle() {
try {
session.incoming.consumeEach { frame ->
for (frame in session.incoming) {
if (frame is Frame.Text) {
val text = frame.readText()
if (!text.isJson()) {
session.send("数据必须为Json格式")
session.close(CloseReason(CloseReason.Codes.NORMAL, "调试结束"))
return@consumeEach
break
}
val debugBean = GSON.fromJsonObject<Map<String, String>>(text).getOrNull()
if (debugBean != null) {
@@ -35,7 +34,7 @@ class RssSourceDebugWebSocket(private val session: DefaultWebSocketServerSession
if (tag.isNullOrBlank()) {
session.send(appCtx.getString(R.string.cannot_empty))
session.close(CloseReason(CloseReason.Codes.NORMAL, "调试结束"))
return@consumeEach
break
}
appDb.rssSourceDao.getByKey(tag)?.let {
Debug.callback = this@RssSourceDebugWebSocket