Open Closed

Dynamic change and apply configuration for File Management at runtime? #9183


User avatar
0
hanntd created

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)
  • User Avatar
    0
    enisn created
    Support Team .NET Developer

    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...
     });
    
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.0.0-preview. Updated on July 14, 2025, 11:57