diff --git a/Learn.VideoAnalysis.API/Expand/HttpFilter.cs b/Learn.VideoAnalysis.API/Expand/HttpFilter.cs index 692d637..e3512e6 100644 --- a/Learn.VideoAnalysis.API/Expand/HttpFilter.cs +++ b/Learn.VideoAnalysis.API/Expand/HttpFilter.cs @@ -54,10 +54,25 @@ namespace Learn.VideoAnalysis.API.Expand /// /// /// - public void ExecutingFileCached(ActionExecutingContext context) + public void ExecutingCached(ActionExecutingContext context) { //特殊处理:ResultIgnore,不进行返回结果包装,原样输出 var endpoint = context.HttpContext.GetEndpoint(); + var request = context.HttpContext.Request; + // 1. 只有非 GET 请求且不是文件上传时才读取 Body + if (!request.Method.Equals("GET", StringComparison.OrdinalIgnoreCase) + && !request.HasFormContentType) + { + // 确保从头开始读 + request.Body.Position = 0; + // 使用 leaveOpen: true 防止 StreamReader 关闭底层的 Request.Body + using (var reader = new System.IO.StreamReader(request.Body, System.Text.Encoding.UTF8, detectEncodingFromByteOrderMarks: false, bufferSize: 1024, leaveOpen: true)) + { + var body = reader.ReadToEnd(); + context.HttpContext.Items["RequestBodyRaw"] = body; + request.Body.Position = 0; + } + } // 直接返回原始结果,不封装 if (endpoint?.Metadata.GetMetadata() == null) return; if (context.HttpContext.Request.HasFormContentType && @@ -74,6 +89,8 @@ namespace Learn.VideoAnalysis.API.Expand }).ToArray(); } + + } /// /// 执行接口前400 处理 @@ -149,54 +166,32 @@ namespace Learn.VideoAnalysis.API.Expand /// public async Task AddHttpLogAsync(HttpContext context, BaseReturn? result = null, Exception? e = null) { - //特殊处理:ResultIgnore,不进行返回结果包装,原样输出 - var endpoint = context.GetEndpoint(); - // 所有请求都记录 - //if (endpoint?.Metadata.GetMetadata() == null&& e is null) return; - string request = null; var logId = Yitter.IdGenerator.YitIdHelper.NextId(); if (!context.Request.Method.Equals("GET", StringComparison.InvariantCultureIgnoreCase)) { - context.Request.EnableBuffering(); - //记录请求参数 - if (context.Request.Body.CanSeek) + var fileArr = context.Items.ContainsKey("FileCached") ? context.Items["FileCached"] as (IFormFile file, MemoryStream stream)[] : null; + if (context.Request.HasFormContentType && fileArr != null) { - try + string uploadsFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "UploadLogs", logId.ToString()); + if (!Directory.Exists(uploadsFolder)) + Directory.CreateDirectory(uploadsFolder); + foreach (var fileInfo in fileArr) { - var fileArr = context.Items.ContainsKey("FileCached") ? context.Items["FileCached"] as (IFormFile file, MemoryStream stream)[] : null; - if (context.Request.HasFormContentType && fileArr != null) - { - // 设置保存目录(例如:项目根目录下的Uploads文件夹) - string uploadsFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "UploadLogs", logId.ToString()); - // 创建目录(如果不存在) - if (!Directory.Exists(uploadsFolder)) - Directory.CreateDirectory(uploadsFolder); - foreach (var fileInfo in fileArr) - { - // 生成安全文件名(防止路径遍历攻击) - string uniqueFileName = Guid.NewGuid().ToString().Substring(0, 5) + "_" + Path.GetFileName(fileInfo.file.FileName); - // 保存文件 - using var stream = new FileStream(Path.Combine(uploadsFolder, uniqueFileName), FileMode.Create, FileAccess.Write); - fileInfo.stream.Position = 0; - await fileInfo.stream.CopyToAsync(stream); - fileInfo.stream.Dispose(); - } - request = $"请求体包含{context.Request.Form.Files.Count()}个文件 目录 {uploadsFolder}"; - } - else - { - context.Request.Body.Position = 0; - using var sr = new System.IO.StreamReader(context.Request.Body); - request = await sr.ReadToEndAsync(); - } - } - catch (Exception ex) - { - request = "处理请求入参时发生了错误 \r\n" + ex.ToString() + "\r\n 原有请求数据 " + request; + string uniqueFileName = Guid.NewGuid().ToString().Substring(0, 5) + "_" + Path.GetFileName(fileInfo.file.FileName); + using var stream = new FileStream(Path.Combine(uploadsFolder, uniqueFileName), FileMode.Create, FileAccess.Write); + fileInfo.stream.Position = 0; + await fileInfo.stream.CopyToAsync(stream); + fileInfo.stream.Dispose(); } + request = $"请求体包含{context.Request.Form.Files.Count()}个文件 目录 {uploadsFolder}"; } + } + if (context.Items.ContainsKey("RequestBodyRaw")) + { + request = context.Items["RequestBodyRaw"] as string; + } //写入队列 await DbScoped.Sugar.CopyNew() .Insertable(new HttpLog @@ -205,7 +200,7 @@ namespace Learn.VideoAnalysis.API.Expand Url = context.Request.Path + context.Request.QueryString, Method = context.Request.Method, Request = request, - IP = $"{context.Connection?.RemoteIpAddress?.ToString()}", + IP = GetClientIp(context), ResponseCode = result?.Code ?? -1, Response = (result != null ? JsonSerializer.Serialize(result) : null) , Authorization = context.Request.Headers.ContainsKey("Authorization") @@ -218,21 +213,31 @@ namespace Learn.VideoAnalysis.API.Expand }).ExecuteCommandAsync(); } + private string GetClientIp(HttpContext context) + { + var headers = context.Request.Headers; + var ip = headers["X-Forwarded-For"].FirstOrDefault(); + if (!string.IsNullOrWhiteSpace(ip)) + { + ip = ip.Split(',', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault()?.Trim(); + } + if (string.IsNullOrWhiteSpace(ip)) + { + ip = headers["X-Real-IP"].FirstOrDefault(); + } + if (string.IsNullOrWhiteSpace(ip) && context.Connection.RemoteIpAddress != null) + { + ip = context.Connection.RemoteIpAddress.ToString(); + } + return ip ?? string.Empty; + } public override async void OnActionExecuting(ActionExecutingContext context) { - // 过期的 - //if (context.HttpContext.GetEndpoint()? - // .Metadata.GetMetadata() is null) - //{ - // context.Result = new UnauthorizedResult(); - // return; - //} - Executing400(context); - ExecutingFileCached(context); - base.OnActionExecuting(context); + ExecutingCached(context); + } /// @@ -248,6 +253,9 @@ namespace Learn.VideoAnalysis.API.Expand } catch (Exception ex) { + Console.WriteLine($"{DateTime.Now}=>接口规范出现异常"); + Console.WriteLine(ex.Message); + Console.WriteLine(ex.StackTrace); } base.OnActionExecuted(context); diff --git a/VideoAnalysis/Program.cs b/VideoAnalysis/Program.cs index 0a82ed1..f6d6179 100644 --- a/VideoAnalysis/Program.cs +++ b/VideoAnalysis/Program.cs @@ -106,8 +106,6 @@ namespace Learn.VideoAnalysis AppCommon.Services = app.Services; app.UseMiddleware("Swagger"); // Configure the HTTP request pipeline. - //开启redis队列服务 - _ = app.Services.GetRequiredService(); app.UseSwagger(); app.UseSwaggerUI(); app.UseExceptionHandler("/Error"); @@ -133,7 +131,12 @@ namespace Learn.VideoAnalysis app.UseCorsExpand(); app.UseSqlSugarExpand(); app.UseCoravelExpand(); - app.UseServiceSystem(); + app.UseServiceSystem(() => + { + //开启redis队列服务 + _ = AppCommon.Services.GetRequiredService(); + + }); app.Run(); diff --git a/VideoAnalysisCore/AICore/GPT/Dto/QuestionRes.cs b/VideoAnalysisCore/AICore/GPT/Dto/QuestionRes.cs index a58af6e..abfde19 100644 --- a/VideoAnalysisCore/AICore/GPT/Dto/QuestionRes.cs +++ b/VideoAnalysisCore/AICore/GPT/Dto/QuestionRes.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; diff --git a/VideoAnalysisCore/AICore/GPT/GTP_Analysis_1.cs b/VideoAnalysisCore/AICore/GPT/GTP_Analysis_1.cs index 2cc197f..5260fd4 100644 --- a/VideoAnalysisCore/AICore/GPT/GTP_Analysis_1.cs +++ b/VideoAnalysisCore/AICore/GPT/GTP_Analysis_1.cs @@ -1,4 +1,4 @@ -using VideoAnalysisCore.Common; +using VideoAnalysisCore.Common; using System.Text.Json; using VideoAnalysisCore.Model; using System.Text; diff --git a/VideoAnalysisCore/Common/AppCommon.cs b/VideoAnalysisCore/Common/AppCommon.cs index 987da8c..0c0cc26 100644 --- a/VideoAnalysisCore/Common/AppCommon.cs +++ b/VideoAnalysisCore/Common/AppCommon.cs @@ -109,7 +109,7 @@ namespace VideoAnalysisCore.Common public static string FrameName = "frame_"; /// - /// 删除 AI分析任务的缓存文件 + /// 删除 AI分析任务视频/PPT的缓存文件 /// /// /// @@ -144,6 +144,32 @@ namespace VideoAnalysisCore.Common return true; } + /// + /// 删除 AI分析任务的缓存文件 + /// + /// + /// + public static async Task DeleteTaskAllFileAsync(long? taskId, RedisManager redisManager) + { + if (taskId is null || taskId == 0) return false; + var path = taskId.ToString().LocalPath(); + if (!string.IsNullOrEmpty(path) && Directory.Exists(path)) + { + try + { + Directory.Delete(path, true); + await redisManager.AddTaskLog(taskId, $"已清理所有缓存文件: {taskId}"); + } + catch (Exception ex) + { + await redisManager.AddTaskLog(taskId, $"删除缓存文件 {taskId} 时出错: {ex.Message}"); + } + } + else + await redisManager.AddTaskLog(taskId, $"未识别到任务缓存: {path}"); + return true; + } + /// /// 对象转化为JSON字符串 /// diff --git a/VideoAnalysisCore/Common/BasicAuthMiddleware.cs b/VideoAnalysisCore/Common/BasicAuthMiddleware.cs index 4317807..8b9cbc4 100644 --- a/VideoAnalysisCore/Common/BasicAuthMiddleware.cs +++ b/VideoAnalysisCore/Common/BasicAuthMiddleware.cs @@ -42,7 +42,9 @@ namespace VideoAnalysisCore.Common context.Response.StatusCode = StatusCodes.Status401Unauthorized; return; } - + if (!context.Request.Method.Equals("GET", StringComparison.OrdinalIgnoreCase) + && !context.Request.HasFormContentType) + context.Request.EnableBuffering(); await _next(context); } diff --git a/VideoAnalysisCore/Common/Expand/ServiceSystem.cs b/VideoAnalysisCore/Common/Expand/ServiceSystem.cs index 9423ac3..0f748a2 100644 --- a/VideoAnalysisCore/Common/Expand/ServiceSystem.cs +++ b/VideoAnalysisCore/Common/Expand/ServiceSystem.cs @@ -24,7 +24,7 @@ namespace VideoAnalysisCore.Common.Expand /// 系统服务 /// /// - public static void UseServiceSystem(this IHost app1) + public static void UseServiceSystem(this IHost app1,Action? action=null) { var app = app1.Services; // 注册启动后的回调 @@ -46,7 +46,10 @@ namespace VideoAnalysisCore.Common.Expand .Replace("+", "127.0.0.1"); var uri = new Uri(normalizedAddress); int port = uri.Port; // 这里的 port 就是你要的数字 (int) - OpenBrowser($"http://localhost:{uri.Port}/ui/index.html"); + if (OperatingSystem.IsWindows()) + OpenBrowser($"http://localhost:{uri.Port}/ui/index.html"); + if(action != null) + action(); }); } diff --git a/VideoAnalysisCore/Common/RedisExpand.cs b/VideoAnalysisCore/Common/RedisExpand.cs index 2a456cd..86ace77 100644 --- a/VideoAnalysisCore/Common/RedisExpand.cs +++ b/VideoAnalysisCore/Common/RedisExpand.cs @@ -414,7 +414,9 @@ namespace VideoAnalysisCore.Common }).ExecuteCommandAsync(); try { - await ExpandFunction.DeleteTaskFileAsync(tId, this); + //await ExpandFunction.DeleteTaskFileAsync(tId, this); + + await ExpandFunction.DeleteTaskAllFileAsync(tId, this); } catch (Exception) { @@ -429,6 +431,7 @@ namespace VideoAnalysisCore.Common /// public async Task InitChannel() { + Thread.Sleep(1000); if (Redis is null) throw new Exception("redis未初始化"); //处理之前程序结束前未能执行完的情况 var oldTaskCount = Redis.LLen(RedisExpandKey.IDTask); diff --git a/VideoAnalysisCore/Controllers/PublicController.cs b/VideoAnalysisCore/Controllers/PublicController.cs index eb660e4..44cdc02 100644 --- a/VideoAnalysisCore/Controllers/PublicController.cs +++ b/VideoAnalysisCore/Controllers/PublicController.cs @@ -13,7 +13,6 @@ namespace VideoAnalysisCore.Controllers /// /// 通用接口 /// - [Authorize(AuthenticationSchemes = Authentication.vdAdmin)] [Route("api/[controller]")] public class PublicController : ControllerBase { diff --git a/VideoAnalysisCore/Job/TaskFileClearJob.cs b/VideoAnalysisCore/Job/TaskFileClearJob.cs index e011188..4fae381 100644 --- a/VideoAnalysisCore/Job/TaskFileClearJob.cs +++ b/VideoAnalysisCore/Job/TaskFileClearJob.cs @@ -31,12 +31,12 @@ namespace VideoAnalysisCore.Job this.videotaskDB = videotaskDB; this.redisManager = redisManager; } - public void DeleteTaskAllCaches() + public async Task DeleteTaskAllCachesAsync() { - var startTime = -5; + var startTime = -2; var timeSpan = startTime - 999; - // 计算 6 天前已完成任务缓存 + // 计算 {startTime} 天前已完成任务缓存 DateTime twoDaysAgo = DateTime.Now.AddDays(startTime); DateTime endDaysAgo = DateTime.Now.AddDays(timeSpan); @@ -54,21 +54,7 @@ namespace VideoAnalysisCore.Job // 遍历查询结果,删除缓存文件 foreach (var taskId in completedTasks) - { - var path = taskId.ToString().LocalPath(); - if (!string.IsNullOrEmpty(path) && Directory.Exists(path)) - { - try - { - Directory.Delete(path, true); - Console.WriteLine($"已删除缓存文件: {taskId}"); - } - catch (Exception ex) - { - Console.WriteLine($"删除缓存文件 {taskId} 时出错: {ex.Message}"); - } - } - } + await ExpandFunction.DeleteTaskAllFileAsync(taskId, redisManager); } public async void DeleteTaskVideoCaches() { @@ -105,7 +91,7 @@ namespace VideoAnalysisCore.Job { Console.WriteLine($"{DateTime.Now} 执行=>{this.GetType().FullName}"); DeleteTaskVideoCaches(); - DeleteTaskAllCaches(); + DeleteTaskAllCachesAsync(); } } }