diff --git a/XRServer/BaseInfoHandler.cs b/XRServer/HttpHandler.cs similarity index 74% rename from XRServer/BaseInfoHandler.cs rename to XRServer/HttpHandler.cs index d3bf3e8..6f6f30c 100644 --- a/XRServer/BaseInfoHandler.cs +++ b/XRServer/HttpHandler.cs @@ -19,7 +19,7 @@ namespace XRServer /// 1. 전체 데이터 요청: /baseinfo/01:23 (01분 23초에 해당하는 전체 baseinfo 데이터를 요청) /// 2. 특정 속성 요청: /Position/01:23 (01분 23초 데이터에서 'Position' 속성만 요청) /// - public class BaseInfoHandler : IHttpRequestHandler + public class HttpHandler : IHttpRequestHandler { private SQLiteService _sqliteService; // 정규식은 매번 컴파일하지 않고, static readonly으로 만들어 한 번만 컴파일하여 재사용하는 것이 성능에 유리합니다. @@ -28,14 +28,19 @@ namespace XRServer /// /// 지정된 콘텐츠의 모든 TIMESTAMP 발생을 현재 시간 UTC TIMESTAMP로 바꿀지 여부 /// - public bool ApplyNowTimeStamp { get; set; } = false; // 현재 시간 스탬프를 적용하지 않습니다. + public bool ApplyNowTimeStamp { get; set; } = false; + + /// + /// Playback 파일이 저장된 폴더의 경로를 가져오거나 설정합니다. + /// + public string PlaybackFolderPath { get; set; } = string.Empty; /// /// BaseInfoHandler의 생성자입니다. /// /// 데이터베이스 작업을 처리하기 위해 외부에서 주입된 SQLiteService 인스턴스입니다. (의존성 주입) - public BaseInfoHandler(SQLiteService sqliteService) + public HttpHandler(SQLiteService sqliteService) { this._sqliteService = sqliteService; } @@ -49,7 +54,14 @@ namespace XRServer { // /baseinfo/분:초(mm:ss format) 문자열을 받아 해당 시간에 대한 SelectBySecondBaseInfo 데이터 반환 string url = context.Request.Uri.OriginalString; - Logger.Debug($"BaseInfoHandler: {url} 요청 처리 중..."); + Logger.Debug($"HttpHandler: {url} 요청 처리 중..."); + + //url이 '/playback/list'로 시작하는 경우, 다음 핸들러로 넘깁니다. + if (url.StartsWith("/playback/list", StringComparison.OrdinalIgnoreCase)) + { + handlePlaybackList(context); + return; // '/playback/list' 요청은 별도로 처리하므로 여기서 종료합니다. + } // 1. URL에서 'mm:ss' 형식의 시간 부분이 있는지 정규식으로 확인합니다. Match match = TimeFormatRegex.Match(url); @@ -113,6 +125,57 @@ namespace XRServer } + private void handlePlaybackList(IHttpContext context) + { + + if(Directory.Exists(PlaybackFolderPath) == false) + { + // 재생 목록 폴더가 존재하지 않으면 404 오류를 반환합니다. + context.Response = new HttpResponse(HttpResponseCode.NotFound, "Playback 폴더가 존재하지 않습니다.", false); + return; + } + + // 아래 같은 형식의 JSON 객체를 반환합니다. + //{ + // "2024-12-05": { + // "0": "2024-12-05_0.sqlite.7z", + // "1": "2024-12-05_1.sqlite.7z", + // "2": "2024-12-05_2.sqlite.7z", + // } + //} + + var playbackList = new JObject(); + // PlaybackFolderPath에서 모든 파일을 검색합니다. + var files = Directory.GetFiles(PlaybackFolderPath, "*.sqlite.7z"); + foreach (var file in files) + { + // 파일 이름에서 날짜와 인덱스를 추출합니다. 예: "2024-12-05_0.sqlite.7z" + string fileName = Path.GetFileNameWithoutExtension(file); // "2024-12-05_0.sqlite" + string[] parts = fileName.Split('_'); // ["2024-12-05", "0"] + if (parts.Length < 2) continue; // 형식이 잘못된 경우 건너뜁니다. + string date = parts[0]; // "2024-12-05" + string index = parts[1]; // "0" + // 날짜가 없으면 새로 추가하고, 있으면 기존에 추가합니다. + if (!playbackList.ContainsKey(date)) + { + playbackList[date] = new JObject(); + } + ((JObject)playbackList[date])[index] = Path.GetFileName(file); // 파일 이름을 추가 + } + + JObject responsePayload = new JObject(); + responsePayload["code"] = 20; // 성공 코드 + responsePayload["message"] = "success"; // 성공 메시지 + responsePayload["data"] = playbackList; // 재생 목록 데이터 + + var headers = new List> + { + new KeyValuePair("Content-Type", "application/json; charset=utf-8"), + }; + + context.Response = new HttpResponse(HttpResponseCode.Ok, responsePayload.ToString(Formatting.None), headers, context.Request.Headers.KeepAliveConnection()); + } + /// /// URL 경로에서 요청 타입을 추출합니다. (예: "baseinfo") /// diff --git a/XRServer/MainWindow.xaml b/XRServer/MainWindow.xaml index cfe6a0b..826b486 100644 --- a/XRServer/MainWindow.xaml +++ b/XRServer/MainWindow.xaml @@ -8,22 +8,24 @@ Title="XR Server" Height="450" Width="840" Closing="Window_Closing" Loaded="Window_Loaded">