Dosya Yöneticisi gerçek zamanlı çalışıyor
This commit is contained in:
parent
fc7e143e4e
commit
c93007cc07
2 changed files with 77 additions and 69 deletions
|
|
@ -9,6 +9,8 @@ using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Kurs.Platform.BlobStoring;
|
using Kurs.Platform.BlobStoring;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Volo.Abp;
|
using Volo.Abp;
|
||||||
using Volo.Abp.Application.Services;
|
using Volo.Abp.Application.Services;
|
||||||
using Volo.Abp.MultiTenancy;
|
using Volo.Abp.MultiTenancy;
|
||||||
|
|
@ -19,6 +21,7 @@ public class FileManagementAppService : ApplicationService, IFileManagementAppSe
|
||||||
{
|
{
|
||||||
private readonly ICurrentTenant _currentTenant;
|
private readonly ICurrentTenant _currentTenant;
|
||||||
private readonly BlobManager _blobContainer;
|
private readonly BlobManager _blobContainer;
|
||||||
|
private readonly IConfiguration _configuration;
|
||||||
|
|
||||||
private const string FileMetadataSuffix = ".metadata.json";
|
private const string FileMetadataSuffix = ".metadata.json";
|
||||||
private const string FolderMarkerSuffix = ".folder";
|
private const string FolderMarkerSuffix = ".folder";
|
||||||
|
|
@ -26,11 +29,13 @@ public class FileManagementAppService : ApplicationService, IFileManagementAppSe
|
||||||
|
|
||||||
public FileManagementAppService(
|
public FileManagementAppService(
|
||||||
ICurrentTenant currentTenant,
|
ICurrentTenant currentTenant,
|
||||||
BlobManager blobContainer
|
BlobManager blobContainer,
|
||||||
|
IConfiguration configuration
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
_currentTenant = currentTenant;
|
_currentTenant = currentTenant;
|
||||||
_blobContainer = blobContainer;
|
_blobContainer = blobContainer;
|
||||||
|
_configuration = configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetTenantPrefix()
|
private string GetTenantPrefix()
|
||||||
|
|
@ -46,68 +51,85 @@ public class FileManagementAppService : ApplicationService, IFileManagementAppSe
|
||||||
|
|
||||||
private async Task<List<FileMetadata>> GetFolderIndexAsync(string? parentId = null)
|
private async Task<List<FileMetadata>> GetFolderIndexAsync(string? parentId = null)
|
||||||
{
|
{
|
||||||
// Root seviyesinde default klasörleri göster
|
return await GetRealCdnContentsAsync(parentId);
|
||||||
if (string.IsNullOrEmpty(parentId))
|
}
|
||||||
|
|
||||||
|
private async Task<List<FileMetadata>> GetRealCdnContentsAsync(string? folderPath)
|
||||||
|
{
|
||||||
|
var items = new List<FileMetadata>();
|
||||||
|
var cdnBasePath = _configuration["App:CdnPath"];
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(cdnBasePath))
|
||||||
{
|
{
|
||||||
var defaultFolders = new List<FileMetadata>
|
Logger.LogWarning("CDN path is not configured");
|
||||||
{
|
return items;
|
||||||
// Default system folders
|
|
||||||
new() {
|
|
||||||
Id = BlobContainerNames.Avatar,
|
|
||||||
Name = "Avatar",
|
|
||||||
Type = "folder",
|
|
||||||
CreatedAt = DateTime.UtcNow,
|
|
||||||
ModifiedAt = DateTime.UtcNow,
|
|
||||||
Path = BlobContainerNames.Avatar,
|
|
||||||
ParentId = "",
|
|
||||||
IsReadOnly = false,
|
|
||||||
TenantId = _currentTenant.Id?.ToString()
|
|
||||||
},
|
|
||||||
new() {
|
|
||||||
Id = BlobContainerNames.Import,
|
|
||||||
Name = "Import",
|
|
||||||
Type = "folder",
|
|
||||||
CreatedAt = DateTime.UtcNow,
|
|
||||||
ModifiedAt = DateTime.UtcNow,
|
|
||||||
Path = BlobContainerNames.Import,
|
|
||||||
ParentId = "",
|
|
||||||
IsReadOnly = false,
|
|
||||||
TenantId = _currentTenant.Id?.ToString()
|
|
||||||
},
|
|
||||||
new() {
|
|
||||||
Id = BlobContainerNames.Activity,
|
|
||||||
Name = "Activity",
|
|
||||||
Type = "folder",
|
|
||||||
CreatedAt = DateTime.UtcNow,
|
|
||||||
ModifiedAt = DateTime.UtcNow,
|
|
||||||
Path = BlobContainerNames.Activity,
|
|
||||||
ParentId = "",
|
|
||||||
IsReadOnly = false,
|
|
||||||
TenantId = _currentTenant.Id?.ToString()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Custom folders from index
|
|
||||||
var customFolders = await GetCustomFoldersAsync();
|
|
||||||
defaultFolders.AddRange(customFolders);
|
|
||||||
|
|
||||||
return defaultFolders;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alt klasörlerin indexini oku
|
var tenantId = _currentTenant.Id?.ToString() ?? "host";
|
||||||
var indexPath = GetTenantPrefix() + $"{parentId}/{IndexFileName}";
|
var fullPath = Path.Combine(cdnBasePath, tenantId);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(folderPath))
|
||||||
|
{
|
||||||
|
fullPath = Path.Combine(fullPath, folderPath);
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var indexBytes = await _blobContainer.GetAllBytesOrNullAsync(indexPath);
|
if (!Directory.Exists(fullPath))
|
||||||
if (indexBytes == null) return new List<FileMetadata>();
|
{
|
||||||
|
Logger.LogWarning($"Directory does not exist: {fullPath}");
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
var indexJson = Encoding.UTF8.GetString(indexBytes);
|
// Klasörleri listele
|
||||||
return JsonSerializer.Deserialize<List<FileMetadata>>(indexJson) ?? new List<FileMetadata>();
|
var directories = Directory.GetDirectories(fullPath);
|
||||||
|
foreach (var dir in directories)
|
||||||
|
{
|
||||||
|
var dirInfo = new DirectoryInfo(dir);
|
||||||
|
var relativePath = string.IsNullOrEmpty(folderPath) ? dirInfo.Name : $"{folderPath}/{dirInfo.Name}";
|
||||||
|
|
||||||
|
items.Add(new FileMetadata
|
||||||
|
{
|
||||||
|
Id = relativePath,
|
||||||
|
Name = dirInfo.Name,
|
||||||
|
Type = "folder",
|
||||||
|
CreatedAt = dirInfo.CreationTime,
|
||||||
|
ModifiedAt = dirInfo.LastWriteTime,
|
||||||
|
Path = relativePath,
|
||||||
|
ParentId = folderPath ?? "",
|
||||||
|
IsReadOnly = false,
|
||||||
|
TenantId = _currentTenant.Id?.ToString()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dosyaları listele
|
||||||
|
var files = Directory.GetFiles(fullPath);
|
||||||
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
var fileInfo = new FileInfo(file);
|
||||||
|
var relativePath = string.IsNullOrEmpty(folderPath) ? fileInfo.Name : $"{folderPath}/{fileInfo.Name}";
|
||||||
|
|
||||||
|
items.Add(new FileMetadata
|
||||||
|
{
|
||||||
|
Id = relativePath,
|
||||||
|
Name = fileInfo.Name,
|
||||||
|
Type = "file",
|
||||||
|
Size = fileInfo.Length,
|
||||||
|
CreatedAt = fileInfo.CreationTime,
|
||||||
|
ModifiedAt = fileInfo.LastWriteTime,
|
||||||
|
Path = relativePath,
|
||||||
|
ParentId = folderPath ?? "",
|
||||||
|
IsReadOnly = false,
|
||||||
|
TenantId = _currentTenant.Id?.ToString()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return items.OrderBy(x => x.Type == "folder" ? 0 : 1).ThenBy(x => x.Name).ToList();
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return new List<FileMetadata>();
|
Logger.LogError(ex, $"Error reading CDN contents from: {fullPath}");
|
||||||
|
return items;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -555,7 +577,7 @@ public class FileManagementAppService : ApplicationService, IFileManagementAppSe
|
||||||
|
|
||||||
private async Task<List<FileMetadata>> GetAllItemsRecursivelyAsync(string? parentId = null, List<FileMetadata>? result = null)
|
private async Task<List<FileMetadata>> GetAllItemsRecursivelyAsync(string? parentId = null, List<FileMetadata>? result = null)
|
||||||
{
|
{
|
||||||
result ??= new List<FileMetadata>();
|
result ??= [];
|
||||||
|
|
||||||
var items = await GetFolderIndexAsync(parentId);
|
var items = await GetFolderIndexAsync(parentId);
|
||||||
result.AddRange(items);
|
result.AddRange(items);
|
||||||
|
|
|
||||||
|
|
@ -269,11 +269,6 @@ const FileManager = () => {
|
||||||
setDeleteModalOpen(true)
|
setDeleteModalOpen(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleDeleteSelected = () => {
|
|
||||||
const itemsToDelete = items.filter((item) => selectedItems.includes(item.id))
|
|
||||||
openDeleteModal(itemsToDelete)
|
|
||||||
}
|
|
||||||
|
|
||||||
const goUpOneLevel = () => {
|
const goUpOneLevel = () => {
|
||||||
if (breadcrumbItems.length > 1) {
|
if (breadcrumbItems.length > 1) {
|
||||||
const parentBreadcrumb = breadcrumbItems[breadcrumbItems.length - 2]
|
const parentBreadcrumb = breadcrumbItems[breadcrumbItems.length - 2]
|
||||||
|
|
@ -311,15 +306,6 @@ const FileManager = () => {
|
||||||
Go Up
|
Go Up
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{selectedItems.length > 0 && (
|
|
||||||
<Button
|
|
||||||
variant="solid"
|
|
||||||
className="bg-red-600 hover:bg-red-700 text-white"
|
|
||||||
onClick={handleDeleteSelected}
|
|
||||||
>
|
|
||||||
Delete Selected ({selectedItems.length})
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue