调整ktor后端:取消api前缀;去除无用代码;oss对象使用临时地址返回;

This commit is contained in:
BBIT-Kai
2025-09-26 16:18:48 +08:00
parent bc5770e59e
commit 381469aff8
10 changed files with 63 additions and 69 deletions
+2 -1
View File
@@ -101,5 +101,6 @@ dependencies {
// 数据库迁移
// implementation("org.flywaydb:flyway-core:10.13.0")
implementation("ai.koog:koog-agents:0.3.0")
// implementation("ai.koog:koog-agents:0.3.0")
implementation("io.minio:minio:8.5.17")
}
@@ -4,7 +4,6 @@ import com.google.gson.Gson
import ink.snowflake.server.controller.User
import ink.snowflake.server.controller.chat
import ink.snowflake.server.utils.plugins.configureSockets
import ink.snowflake.server.controller.LLM
import ink.snowflake.server.controller.ImageAnalytics
import ink.snowflake.server.controller.RemoteDebug
import ink.snowflake.server.controller.VideoAnalytics
@@ -29,12 +28,6 @@ const val VIDEO_INPUT_PATH = "C:/tmp/"
* ADB 秦朗FRP地址
*/
const val SERVER_PATH_FRP = "s3.ronsunny.cn" // 171.212.101.201
/**
* 服务器地址
* OSS 对象存储服务器地址
*/
const val SERVER_PATH_OSS = "s1.ronsunny.cn" // 171.212.101.199
val gson = Gson()
fun main(args: Array<String>): Unit = EngineMain.main(args)
@@ -72,6 +65,4 @@ fun Application.module() {
VideoAnalyticsJetson()
// 业务-图片分析
ImageAnalytics()
// 业务-AI
LLM()
}
@@ -11,7 +11,7 @@ import io.ktor.server.response.*
fun Application.ImageAnalytics() {
routing {
route("/api/sca") {
route("/sca") {
// 上传分析结果
post("/saveImageAnalyticsData") {
val request = call.receive<ImageAnalyticsRequest>()
@@ -1,45 +0,0 @@
package ink.snowflake.server.controller
import ai.koog.agents.core.agent.AIAgent
import ai.koog.prompt.executor.llms.all.simpleOllamaAIExecutor
import ai.koog.prompt.llm.LLMCapability
import ai.koog.prompt.llm.LLMProvider
import ai.koog.prompt.llm.LLModel
import ink.snowflake.server.SERVER_PATH_OSS
import ink.snowflake.server.model.response.AiListForUserResponse
import ink.snowflake.server.model.response.BaseResponse
import ink.snowflake.server.model.response.SessionListResponse
import ink.snowflake.server.utils.TokenUtils.getUserIdByToken
import ink.snowflake.server.utils.dao.AIDao
import io.ktor.server.application.Application
import io.ktor.server.auth.authenticate
import io.ktor.server.response.respond
import io.ktor.server.routing.get
import io.ktor.server.routing.route
import io.ktor.server.routing.routing
import kotlinx.html.Entities
fun Application.LLM() {
routing {
route("/api/llm") {
// authenticate {
// get("/getAiList") {
// val allAIProfile = AIDao.getAllAIProfiles().map {
// AiListForUserResponse(
// id = it.id,
// name = it.name ?: "",
// welcomeWords = it.welcome_words ?: ""
// )
// }
// call.respond(BaseResponse(data = allAIProfile))
// }
// get("/getSessions") {
// val userId = getUserIdByToken(call)
// val sessionList = AIDao.getSessionList(userId)
// call.respond(BaseResponse(data = sessionList))
// }
// }
}
}
}
@@ -40,7 +40,6 @@ fun Application.RemoteDebug() {
}
}
routing {
route("/api") {
authenticate {
route("/remote") {
get("/connect") {
@@ -100,7 +99,6 @@ fun Application.RemoteDebug() {
}
}
}
}
}
webSocket("/logStream") {
send("日志系统连接成功")
@@ -155,7 +153,6 @@ fun Application.RemoteDebug() {
clients.remove(this)
}
}
}
}
@@ -38,7 +38,7 @@ import kotlin.text.Charsets.UTF_8
// 配置和初始化 Redis 客户端
fun setupRedis(): RedissonClient {
val config = Config()
config.useSingleServer().setAddress("redis://localhost:6379")
config.useSingleServer().setAddress("redis://10.10.10.9:6379")
return Redisson.create(config)
}
@@ -46,7 +46,7 @@ fun Application.User(config: AppConfig) {
// 初始化 Redis 连接
val redisClient: RedissonClient = setupRedis()
routing {
route("/api/user") {
route("/user") {
post("/login") {
val loginRequest = call.receive<LoginRequest>()
val email = loginRequest.account
@@ -1,7 +1,7 @@
package ink.snowflake.server.controller
import ink.snowflake.server.SERVER_PATH_OSS
import ink.snowflake.server.VIDEO_INPUT_PATH
import ink.snowflake.server.model.database.ScaImagesTable
import ink.snowflake.server.utils.dao.VideoDao
import ink.snowflake.server.model.database.VideosTable
import ink.snowflake.server.model.database.VideosTable.vAAverageMaskedRatio
@@ -15,6 +15,7 @@ import ink.snowflake.server.model.response.*
import ink.snowflake.server.utils.CommandUtils.runCommand
import ink.snowflake.server.utils.MyUtils
import ink.snowflake.server.utils.MyUtils.getFriendlyActionName
import ink.snowflake.server.utils.OSSUtils
import ink.snowflake.server.utils.WebSocketManager.broadcastMessage
import io.ktor.http.content.*
import io.ktor.server.application.*
@@ -38,7 +39,7 @@ val clients = Collections.synchronizedList<WebSocketServerSession>(ArrayList())
fun Application.VideoAnalytics() {
routing {
route("/api/iva") {
route("/iva") {
// 上传分析结果
post("/saveVideoAnalyticsData") {
val request = call.receive<VideoAnalyticsRequest>()
@@ -218,7 +219,7 @@ fun Application.VideoAnalytics() {
data = VideoAnalyticsDetail(
v_id = vId,
v_name = video[VideosTable.vName],
v_video_play_path = "http://${SERVER_PATH_OSS}:9000/video/" + video[VideosTable.vObjectName],
v_video_play_path = OSSUtils.getPresignedUrl("video",video[VideosTable.vObjectName]),
v_file_name = video[VideosTable.vFileName],
v_duration = video[VideosTable.vDuration],
v_size = video[VideosTable.vSize],
@@ -26,7 +26,6 @@ fun Application.VideoAnalyticsJetson() {
webSocket("/handleState1") {
}
route("/api") {
static("/camera/stream") {
// files("camera/stream") // 确保 FFmpeg 输出的 HLS 片段和 m3u8 文件存放在这里
files(File(streamFile))
@@ -65,7 +64,6 @@ fun Application.VideoAnalyticsJetson() {
call.respond(BaseResponse(message = "摄像头流已停止", data = null))
}
}
}
}
// 确保应用退出时清理所有 FFmpeg 进程
@@ -0,0 +1,51 @@
package ink.snowflake.server.utils
import io.minio.MinioClient
import io.minio.PutObjectArgs
import io.minio.GetPresignedObjectUrlArgs
import io.minio.http.Method
import java.io.InputStream
import java.util.concurrent.TimeUnit
object OSSUtils {
private val client: MinioClient = MinioClient.builder()
.endpoint("http://10.10.10.9:9000") // 你的MinIO地址
.credentials("minioadmin", "minioadmin") // 账号密码
.build()
/**
* 上传文件
* @param bucket 桶名
* @param objName 对象名(路径也放这里,例如 "images/test.png"
* @param input 输入流
* @param size 文件大小(字节)
* @param contentType 文件MIME类型,比如 "image/png"
*/
fun uploadFile(bucket: String, objName: String, input: InputStream, size: Long, contentType: String) {
client.putObject(
PutObjectArgs.builder()
.bucket(bucket)
.`object`(objName)
.stream(input, size, -1) // -1 表示不限制分片大小,MinIO自己切
.contentType(contentType)
.build()
)
}
/**
* 获取临时访问地址
* @param bucket 桶名
* @param objName 对象名
* @param expiryMinutes 过期时间,分钟
*/
fun getPresignedUrl(bucket: String, objName: String, expiryMinutes: Int = 15): String {
return client.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucket)
.`object`(objName)
.expiry(expiryMinutes, TimeUnit.MINUTES)
.build()
)
}
}
@@ -1,9 +1,9 @@
package ink.snowflake.server.utils.dao
import ink.snowflake.server.SERVER_PATH_OSS
import ink.snowflake.server.model.request.ImageAnalyticsRequest
import ink.snowflake.server.model.database.ScaImagesTable
import ink.snowflake.server.utils.MyUtils.formatLocalDateTimeToString
import ink.snowflake.server.utils.OSSUtils
import kotlinx.datetime.toKotlinLocalDateTime
import org.jetbrains.exposed.v1.core.SortOrder
import org.jetbrains.exposed.v1.jdbc.insert
@@ -43,8 +43,8 @@ object ImageDao {
name = it[ScaImagesTable.name],
upload_datetime = formatLocalDateTimeToString(it[ScaImagesTable.upload_datetime]),
file_name = it[ScaImagesTable.file_name],
image_pre = "http://${SERVER_PATH_OSS}:9000/image-sca/raw/" + it[ScaImagesTable.image_pre],
image_after = "http://${SERVER_PATH_OSS}:9000/image-sca/ai/" + it[ScaImagesTable.image_after],
image_pre = OSSUtils.getPresignedUrl("image-sca","raw/" + it[ScaImagesTable.image_pre]),
image_after = OSSUtils.getPresignedUrl("image-sca","ai/" + it[ScaImagesTable.image_after]),
resolution = it[ScaImagesTable.resolution],
size = it[ScaImagesTable.size],
cocoon_count = it[ScaImagesTable.cocoon_count],