diff --git a/api/src/Kurs.Platform.Application/FileManagement/FileManagementAppService.cs b/api/src/Kurs.Platform.Application/FileManagement/FileManagementAppService.cs index ef803843..632c6b94 100644 --- a/api/src/Kurs.Platform.Application/FileManagement/FileManagementAppService.cs +++ b/api/src/Kurs.Platform.Application/FileManagement/FileManagementAppService.cs @@ -48,6 +48,18 @@ public class FileManagementAppService : ApplicationService, IFileManagementAppSe return Guid.NewGuid().ToString("N"); } + private string EncodePathAsId(string path) + { + // Path'deki '/' karakterlerini '|' ile değiştir URL-safe hale getirmek için + return path.Replace("/", "|"); + } + + private string DecodeIdAsPath(string id) + { + // ID'deki '|' karakterlerini '/' ile geri değiştir + return id.Replace("|", "/"); + } + private async Task> GetFolderIndexAsync(string? parentId = null) { return await GetRealCdnContentsAsync(parentId); @@ -89,7 +101,7 @@ public class FileManagementAppService : ApplicationService, IFileManagementAppSe items.Add(new FileMetadata { - Id = relativePath, + Id = EncodePathAsId(relativePath), Name = dirInfo.Name, Type = "folder", CreatedAt = dirInfo.CreationTime, @@ -110,7 +122,7 @@ public class FileManagementAppService : ApplicationService, IFileManagementAppSe items.Add(new FileMetadata { - Id = relativePath, + Id = EncodePathAsId(relativePath), Name = fileInfo.Name, Type = "file", Size = fileInfo.Length, @@ -170,7 +182,8 @@ public class FileManagementAppService : ApplicationService, IFileManagementAppSe public async Task GetItemsByParentAsync(string parentId) { - return await GetItemsInternalAsync(parentId); + var decodedParentId = DecodeIdAsPath(parentId); + return await GetItemsInternalAsync(decodedParentId); } private async Task GetItemsInternalAsync(string? parentId) @@ -208,9 +221,11 @@ public class FileManagementAppService : ApplicationService, IFileManagementAppSe var tenantId = _currentTenant.Id?.ToString() ?? "host"; var parentPath = Path.Combine(cdnBasePath, tenantId); + string? decodedParentId = null; if (!string.IsNullOrEmpty(input.ParentId)) { - parentPath = Path.Combine(parentPath, input.ParentId); + decodedParentId = DecodeIdAsPath(input.ParentId); + parentPath = Path.Combine(parentPath, decodedParentId); } var folderPath = Path.Combine(parentPath, input.Name); @@ -230,15 +245,17 @@ public class FileManagementAppService : ApplicationService, IFileManagementAppSe // Klasörü oluştur Directory.CreateDirectory(folderPath); + var newFolderPath = string.IsNullOrEmpty(decodedParentId) ? input.Name : $"{decodedParentId}/{input.Name}"; + var metadata = new FileMetadata { - Id = string.IsNullOrEmpty(input.ParentId) ? input.Name : $"{input.ParentId}/{input.Name}", + Id = EncodePathAsId(newFolderPath), Name = input.Name, Type = "folder", CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow, - Path = string.IsNullOrEmpty(input.ParentId) ? input.Name : $"{input.ParentId}/{input.Name}", - ParentId = input.ParentId ?? string.Empty, + Path = newFolderPath, + ParentId = decodedParentId ?? string.Empty, IsReadOnly = false, TenantId = _currentTenant.Id?.ToString() }; @@ -260,19 +277,25 @@ public class FileManagementAppService : ApplicationService, IFileManagementAppSe { ValidateFileName(input.FileName); - var items = await GetFolderIndexAsync(input.ParentId); + // Decode parent ID if provided + string? decodedParentId = null; + if (!string.IsNullOrEmpty(input.ParentId)) + { + decodedParentId = DecodeIdAsPath(input.ParentId); + } + + var items = await GetFolderIndexAsync(decodedParentId); if (items.Any(x => x.Name.Equals(input.FileName, StringComparison.OrdinalIgnoreCase))) { throw new UserFriendlyException("A file with this name already exists"); } - var fileId = GenerateFileId(); - var filePath = string.IsNullOrEmpty(input.ParentId) + var filePath = string.IsNullOrEmpty(decodedParentId) ? input.FileName - : $"{input.ParentId}/{input.FileName}"; + : $"{decodedParentId}/{input.FileName}"; - var blobPath = GetTenantPrefix() + filePath; + var fileId = EncodePathAsId(filePath); // Save file content to CDN path var cdnBasePath = _configuration["App:CdnPath"]; @@ -284,9 +307,9 @@ public class FileManagementAppService : ApplicationService, IFileManagementAppSe var tenantId = _currentTenant.Id?.ToString() ?? "host"; var fullCdnPath = Path.Combine(cdnBasePath, tenantId); - if (!string.IsNullOrEmpty(input.ParentId)) + if (!string.IsNullOrEmpty(decodedParentId)) { - fullCdnPath = Path.Combine(fullCdnPath, input.ParentId); + fullCdnPath = Path.Combine(fullCdnPath, decodedParentId); } // Dizini oluştur @@ -325,14 +348,12 @@ public class FileManagementAppService : ApplicationService, IFileManagementAppSe CreatedAt = DateTime.UtcNow, ModifiedAt = DateTime.UtcNow, Path = filePath, - ParentId = input.ParentId ?? string.Empty, + ParentId = decodedParentId ?? string.Empty, IsReadOnly = false, TenantId = _currentTenant.Id?.ToString() }; - // Update parent index - items.Add(metadata); - await SaveFolderIndexAsync(items, input.ParentId); + // File system'e kaydedildi, index güncellemeye gerek yok return new FileItemDto { @@ -485,7 +506,8 @@ public class FileManagementAppService : ApplicationService, IFileManagementAppSe } var tenantId = _currentTenant.Id?.ToString() ?? "host"; - var fullPath = Path.Combine(cdnBasePath, tenantId, id); + var actualPath = DecodeIdAsPath(id); + var fullPath = Path.Combine(cdnBasePath, tenantId, actualPath); if (Directory.Exists(fullPath)) { @@ -512,7 +534,8 @@ public class FileManagementAppService : ApplicationService, IFileManagementAppSe } var tenantId = _currentTenant.Id?.ToString() ?? "host"; - var fullFilePath = Path.Combine(cdnBasePath, tenantId, id); + var actualPath = DecodeIdAsPath(id); + var fullFilePath = Path.Combine(cdnBasePath, tenantId, actualPath); if (!File.Exists(fullFilePath)) { @@ -557,38 +580,7 @@ public class FileManagementAppService : ApplicationService, IFileManagementAppSe public async Task GetFolderPathAsync(string? folderId = null) { - var path = new List(); - - if (string.IsNullOrEmpty(folderId)) - { - return new FolderPathDto { Path = path }; - } - - var metadata = await FindItemMetadataAsync(folderId); - if (metadata == null || metadata.Type != "folder") - { - throw new UserFriendlyException("Folder not found"); - } - - var pathParts = metadata.Path.Split('/', StringSplitOptions.RemoveEmptyEntries); - var currentPath = ""; - - foreach (var part in pathParts) - { - currentPath = string.IsNullOrEmpty(currentPath) ? part : $"{currentPath}/{part}"; - var folderMetadata = await FindItemByPathAsync(currentPath); - - if (folderMetadata != null) - { - path.Add(new PathItemDto - { - Id = folderMetadata.Id, - Name = folderMetadata.Name - }); - } - } - - return new FolderPathDto { Path = path }; + return await GetFolderPathInternalAsync(folderId); } #region Private Helper Methods @@ -698,21 +690,30 @@ public class FileManagementAppService : ApplicationService, IFileManagementAppSe return new FolderPathDto { Path = pathItems }; } - // Reconstruct path from folderId - var currentPath = folderId; - var pathParts = currentPath.Split('/', StringSplitOptions.RemoveEmptyEntries); + // Decode the folderId to get the actual path + var decodedPath = DecodeIdAsPath(folderId); + Logger.LogInformation($"GetFolderPath - FolderId: {folderId}, DecodedPath: {decodedPath}"); - var reconstructedPath = ""; - foreach (var part in pathParts) + // Split path into parts and build breadcrumb + var pathParts = decodedPath.Split('/', StringSplitOptions.RemoveEmptyEntries); + var currentEncodedPath = ""; + + for (int i = 0; i < pathParts.Length; i++) { - reconstructedPath = string.IsNullOrEmpty(reconstructedPath) ? part : $"{reconstructedPath}/{part}"; + // Build the path up to current level + var pathUpToCurrent = string.Join("/", pathParts.Take(i + 1)); + currentEncodedPath = EncodePathAsId(pathUpToCurrent); + + Logger.LogInformation($"PathItem {i}: Name='{pathParts[i]}', Id='{currentEncodedPath}', PathUpToCurrent='{pathUpToCurrent}'"); + pathItems.Add(new PathItemDto { - Id = reconstructedPath, - Name = part + Id = currentEncodedPath, + Name = pathParts[i] // Use the actual folder name, not encoded path }); } + Logger.LogInformation($"Returning {pathItems.Count} breadcrumb items"); return new FolderPathDto { Path = pathItems }; } diff --git a/ui/src/views/admin/files/FileManager.tsx b/ui/src/views/admin/files/FileManager.tsx index e0f22bf4..0773d51e 100644 --- a/ui/src/views/admin/files/FileManager.tsx +++ b/ui/src/views/admin/files/FileManager.tsx @@ -78,6 +78,7 @@ const FileManager = () => { } const response = await fileManagementService.getFolderPath(folderId) + console.log('Breadcrumb response for folderId:', folderId, response) const pathItems: BreadcrumbItem[] = [ { name: 'Files', path: '', id: undefined }, ...response.data.path.map((item) => ({