Hi ABP Team,
In my solution I have many blob storage with different provider (aws, azure, database...)
I'd like to build a page that can help to manage content of each blob storage using File Management. This page allow user to select which blob container to view the content and file management will show the content of selected blob. I tried to configure at runtime but it always get the default blob in database.
How we can apply the configuration to file management at runtime?
thanks,
Dharma
1 Answer(s)
-
0
Hi,
I checked the File-management module and found some ways to do it.
If you have access to the source code, I can** recommend to you downloading the source** code and take a look at to source code to find another implementation that fits your requirements better.
As I understand the case, the following way should work:
Looking at the code, the key components we need to modify are:
- The
FileDescriptorAppService
which uses IBlobContainer<FileManagementContainer> - The
DirectoryDescriptorAppService
which manages the directory structure
- First, create a custom blob container selector service:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Volo.Abp.BlobStoring; using Volo.Abp.DependencyInjection; using Volo.Abp.MultiTenancy; using Volo.Abp.Users; namespace AbpSolution; public interface IBlobContainerSelector { Task<string> GetCurrentContainerNameAsync(); } public class YourBlobContainerSelector : IBlobContainerSelector, ITransientDependency { private readonly ICurrentUser _currentUser; private readonly ICurrentTenant _currentTenant; public YourBlobContainerSelector( ICurrentUser currentUser, ICurrentTenant currentTenant) { _currentUser = currentUser; _currentTenant = currentTenant; } public async Task<string> GetCurrentContainerNameAsync() { // Implement your logic to select the container // This could be based on user selection, tenant, or other criteria return "selected-container-name"; } }
- Create a custom blob container factory:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Volo.Abp.BlobStoring; using Volo.Abp.DependencyInjection; using Volo.Abp.MultiTenancy; using Volo.Abp.Users; namespace AbpSolution; public interface ICustomBlobContainerFactory { Task<IBlobContainer> GetContainerAsync(); } public class CustomBlobContainerFactory : ICustomBlobContainerFactory { private readonly IBlobContainerSelector _containerSelector; private readonly IBlobContainerFactory _blobContainerFactory; public CustomBlobContainerFactory( IBlobContainerSelector containerSelector, IBlobContainerFactory blobContainerFactory) { _containerSelector = containerSelector; _blobContainerFactory = blobContainerFactory; } public async Task<IBlobContainer> GetContainerAsync() { var containerName = await _containerSelector.GetCurrentContainerNameAsync(); return _blobContainerFactory.Create(containerName); } }
- Override the FileDescriptorAppService:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Options; using Volo.Abp.Application.Dtos; using Volo.Abp.Data; using Volo.Abp.Features; using Volo.Abp.ObjectExtending; using Volo.FileManagement.Authorization; using Volo.FileManagement.Files; namespace Volo.FileManagement.Directories; [RequiresFeature(FileManagementFeatures.Enable)] [Authorize(FileManagementPermissions.DirectoryDescriptor.Default)] public class DirectoryDescriptorAppService : FileManagementAppService, IDirectoryDescriptorAppService { protected IDirectoryManager DirectoryManager { get; } protected IDirectoryDescriptorRepository DirectoryDescriptorRepository { get; } protected IFileManager FileManager { get; } protected IFileDescriptorRepository FileDescriptorRepository { get; } protected FileIconOption FileIconOption { get; } public DirectoryDescriptorAppService( IDirectoryManager directoryManager, IFileManager fileManager, IDirectoryDescriptorRepository directoryDescriptorRepository, IFileDescriptorRepository fileDescriptorRepository, IOptions<FileIconOption> fileIconOption) { DirectoryManager = directoryManager; FileManager = fileManager; DirectoryDescriptorRepository = directoryDescriptorRepository; FileDescriptorRepository = fileDescriptorRepository; FileIconOption = fileIconOption.Value; } public virtual async Task<DirectoryDescriptorDto> GetAsync(Guid id) { var directoryDescriptor = await DirectoryDescriptorRepository.GetAsync(id); return ObjectMapper.Map<DirectoryDescriptor, DirectoryDescriptorDto>(directoryDescriptor); } public virtual async Task<ListResultDto<DirectoryDescriptorInfoDto>> GetListAsync(Guid? parentId) { var subDirectories = await DirectoryDescriptorRepository.GetChildrenAsync(parentId); var result = new List<DirectoryDescriptorInfoDto>(); foreach (var subDirectory in subDirectories) { result.Add(new DirectoryDescriptorInfoDto { Name = subDirectory.Name, Id = subDirectory.Id, ParentId = subDirectory.ParentId, HasChildren = await DirectoryDescriptorRepository.ContainsAnyAsync(subDirectory.Id, false) }); } return new ListResultDto<DirectoryDescriptorInfoDto>(result); } [Authorize(FileManagementPermissions.DirectoryDescriptor.Create)] public virtual async Task<DirectoryDescriptorDto> CreateAsync(CreateDirectoryInput input) { var directoryDescriptor = await DirectoryManager.CreateAsync(input.Name, input.ParentId, CurrentTenant.Id); input.MapExtraPropertiesTo(directoryDescriptor); await DirectoryDescriptorRepository.InsertAsync(directoryDescriptor); return ObjectMapper.Map<DirectoryDescriptor, DirectoryDescriptorDto>(directoryDescriptor); } [Authorize(FileManagementPermissions.DirectoryDescriptor.Update)] public virtual async Task<DirectoryDescriptorDto> RenameAsync(Guid id, RenameDirectoryInput input) { var directory = await DirectoryDescriptorRepository.GetAsync(id); directory.SetConcurrencyStampIfNotNull(input.ConcurrencyStamp); await DirectoryManager.RenameAsync(directory, input.Name); await DirectoryDescriptorRepository.UpdateAsync(directory); return ObjectMapper.Map<DirectoryDescriptor, DirectoryDescriptorDto>(directory); } public virtual async Task<PagedResultDto<DirectoryContentDto>> GetContentAsync(DirectoryContentRequestInput input) { var result = new List<DirectoryContentDto>(); var subDirectoryCount = await DirectoryDescriptorRepository.GetChildrenCountAsync(input.Id, input.Filter); var subFileCount = await FileDescriptorRepository.CountDirectoryFilesAsync(input.Id, input.Filter); // directory can be orderable for only its name var directorySorting = input.Sorting?.IndexOf("name asc", StringComparison.OrdinalIgnoreCase) >= 0 ? "name asc" : input.Sorting?.IndexOf("name desc", StringComparison.OrdinalIgnoreCase) >= 0 ? "name desc" : null; var subDirectories = await DirectoryDescriptorRepository.GetChildrenAsync(input.Id, input.Filter, directorySorting, input.MaxResultCount, input.SkipCount); result.AddRange(ObjectMapper.Map<List<DirectoryDescriptor>, List<DirectoryContentDto>>(subDirectories)); if (await AuthorizationService.IsGrantedAsync(FileManagementPermissions.FileDescriptor.Default)) { var fileSkipCount = input.SkipCount <= subDirectoryCount ? 0 : input.SkipCount - subDirectoryCount; var fileMaxResultCount = input.MaxResultCount - subDirectories.Count; var subFiles = await FileDescriptorRepository.GetListAsync(input.Id, input.Filter, input.Sorting, fileMaxResultCount, fileSkipCount); var subFilesDto = ObjectMapper.Map<List<FileDescriptor>, List<DirectoryContentDto>>(subFiles); foreach (var fileDto in subFilesDto) { fileDto.IconInfo = FileIconOption.GetFileIconInfo(fileDto.Name); result.Add(fileDto); } } return new PagedResultDto<DirectoryContentDto>(subDirectoryCount + subFileCount, result); } [Authorize(FileManagementPermissions.DirectoryDescriptor.Delete)] public virtual async Task DeleteAsync(Guid id) { await DirectoryManager.DeleteAsync(id); } [Authorize(FileManagementPermissions.DirectoryDescriptor.Update)] public virtual async Task<DirectoryDescriptorDto> MoveAsync(MoveDirectoryInput input) { var directory = await DirectoryDescriptorRepository.GetAsync(input.Id); directory.SetConcurrencyStampIfNotNull(input.ConcurrencyStamp); await DirectoryManager.MoveAsync(directory, input.NewParentId); await DirectoryDescriptorRepository.UpdateAsync(directory); return ObjectMapper.Map<DirectoryDescriptor, DirectoryDescriptorDto>(directory); } }
- Configure the blob containers in your module class:
Configure<AbpBlobStoringOptions>(options => { // Configure your blob containers options.Containers.Configure("container1", container => { container.UseDatabase(); // Add other configuration as needed }); options.Containers.Configure("container2", container => { container.UseAzure(options => { /* ... */}); // Add other configuration as needed }); // ...and more... });
- The