diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/AbpLocalizationDynamicModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/AbpLocalizationDynamicModule.cs index c9a212d21..d0a007a24 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/AbpLocalizationDynamicModule.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/AbpLocalizationDynamicModule.cs @@ -1,13 +1,18 @@ -using Volo.Abp.EventBus; -using Volo.Abp.Localization; -using Volo.Abp.Modularity; - -namespace LINGYUN.Abp.Localization.Dynamic -{ - [DependsOn( - typeof(AbpEventBusModule), - typeof(AbpLocalizationModule))] - public class AbpLocalizationDynamicModule : AbpModule - { - } -} +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.EventBus; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.Localization.Dynamic +{ + [DependsOn( + typeof(AbpEventBusModule), + typeof(AbpLocalizationModule))] + public class AbpLocalizationDynamicModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddHostedService(); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/AbpLocalizationDynamicOptions.cs b/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/AbpLocalizationDynamicOptions.cs new file mode 100644 index 000000000..397534ee8 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/AbpLocalizationDynamicOptions.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using Volo.Abp.Localization; + +namespace LINGYUN.Abp.Localization.Dynamic +{ + public class AbpLocalizationDynamicOptions + { + internal LocalizationDictionary LocalizationDictionary { get; } + + public AbpLocalizationDynamicOptions() + { + LocalizationDictionary = new LocalizationDictionary(); + } + + internal void AddOrUpdate(string resourceName, Dictionary dictionares) + { + var _dictionares = LocalizationDictionary + .GetOrAdd(resourceName, () => new Dictionary()); + _dictionares.AddIfNotContains(dictionares); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/DynamicLocalizationInitializeService.cs b/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/DynamicLocalizationInitializeService.cs new file mode 100644 index 000000000..40c720c68 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/DynamicLocalizationInitializeService.cs @@ -0,0 +1,45 @@ +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Options; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.Localization; + +namespace LINGYUN.Abp.Localization.Dynamic +{ + public class DynamicLocalizationInitializeService : IHostedService + { + protected ILocalizationStore Store { get; } + protected AbpLocalizationOptions LocalizationOptions { get; } + protected AbpLocalizationDynamicOptions DynamicOptions { get; } + + public DynamicLocalizationInitializeService( + ILocalizationStore store, + IOptions localizationOptions, + IOptions dynamicOptions) + { + Store = store; + DynamicOptions = dynamicOptions.Value; + LocalizationOptions = localizationOptions.Value; + } + + public virtual async Task StartAsync(CancellationToken cancellationToken) + { + foreach (var resource in LocalizationOptions.Resources) + { + foreach (var contributor in resource.Value.Contributors) + { + if (contributor.GetType().IsAssignableFrom(typeof(DynamicLocalizationResourceContributor))) + { + var resourceLocalizationDic = await Store.GetLocalizationDictionaryAsync(resource.Value.ResourceName); + DynamicOptions.AddOrUpdate(resource.Value.ResourceName, resourceLocalizationDic); + } + } + } + } + + public Task StopAsync(CancellationToken cancellationToken) + { + return Task.CompletedTask; + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/DynamicLocalizationResourceContributor.cs b/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/DynamicLocalizationResourceContributor.cs index 2ba17d4cd..8168c001a 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/DynamicLocalizationResourceContributor.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/DynamicLocalizationResourceContributor.cs @@ -1,120 +1,41 @@ -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Localization; -using Microsoft.Extensions.Logging; -using Nito.AsyncEx; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Volo.Abp.Localization; -using Volo.Abp.Threading; - -namespace LINGYUN.Abp.Localization.Dynamic -{ - public class DynamicLocalizationResourceContributor : ILocalizationResourceContributor - { - private ILogger _logger; - private ILocalizationSubscriber _subscriber; - - private ILocalizationStore _store; - protected ILocalizationStore Store => _store; - - private Dictionary _dictionaries; - - private readonly string _resourceName; - private readonly AsyncLock _asyncLock = new AsyncLock(); - - public DynamicLocalizationResourceContributor(string resourceName) - { - _resourceName = resourceName; - } - - public virtual void Initialize(LocalizationResourceInitializationContext context) - { - _logger = context.ServiceProvider.GetService>(); - - _store = context.ServiceProvider.GetRequiredService(); - _subscriber = context.ServiceProvider.GetRequiredService(); - _subscriber.Subscribe(OnChanged); - } - - public virtual void Fill(string cultureName, Dictionary dictionary) - { - GetDictionaries().GetOrDefault(cultureName)?.Fill(dictionary); - } - - public virtual LocalizedString GetOrNull(string cultureName, string name) - { - return GetDictionaries().GetOrDefault(cultureName)?.GetOrNull(name); - } - - protected virtual Dictionary GetDictionaries() - { - var dictionaries = _dictionaries; - if (dictionaries != null) - { - return dictionaries; - } - - try - { - using (_asyncLock.Lock()) - { - dictionaries = _dictionaries = AsyncHelper.RunSync(async () => - await Store.GetLocalizationDictionaryAsync(_resourceName)); - } - } - catch(Exception ex) - { - // 错误不应该影响到应用程序,而是记录到日志 - _logger?.LogWarning("Failed to get localized text, error: ", ex.Message); - } - - return dictionaries; - } - - private Task OnChanged(LocalizedStringCacheResetEventData data) - { - if (string.Equals(_resourceName, data.ResourceName)) - { - if (!_dictionaries.ContainsKey(data.CultureName)) - { - // TODO: 需要处理 data.Key data.Value 空引用 - var dictionary = new Dictionary(); - dictionary.Add(data.Key, new LocalizedString(data.Key, data.Value.NormalizeLineEndings())); - var newLocalizationDictionary = new StaticLocalizationDictionary(data.CultureName, dictionary); - - _dictionaries.Add(data.CultureName, newLocalizationDictionary); - } - else - { - // 取出当前的缓存写入到新字典进行处理 - var nowLocalizationDictionary = _dictionaries[data.CultureName]; - var dictionary = new Dictionary(); - nowLocalizationDictionary.Fill(dictionary); - - var existsKey = dictionary.ContainsKey(data.Key); - if (!existsKey) - { - // 如果不存在,则新增 - dictionary.Add(data.Key, new LocalizedString(data.Key, data.Value.NormalizeLineEndings())); - } - else if (existsKey && data.IsDeleted) - { - // 如果删掉了本地化的节点,删掉当前的缓存 - dictionary.Remove(data.Key); - } - - var newLocalizationDictionary = new StaticLocalizationDictionary(data.CultureName, dictionary); - - if (newLocalizationDictionary != null) - { - // 重新赋值变更过的缓存 - _dictionaries[data.CultureName] = newLocalizationDictionary; - } - } - } - - return Task.CompletedTask; - } - } -} +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Options; +using System.Collections.Generic; +using Volo.Abp.Localization; + +namespace LINGYUN.Abp.Localization.Dynamic +{ + public class DynamicLocalizationResourceContributor : ILocalizationResourceContributor + { + private readonly string _resourceName; + + private AbpLocalizationDynamicOptions _options; + + public DynamicLocalizationResourceContributor(string resourceName) + { + _resourceName = resourceName; + } + + public virtual void Initialize(LocalizationResourceInitializationContext context) + { + _options = context.ServiceProvider.GetService>().Value; + } + + public virtual void Fill(string cultureName, Dictionary dictionary) + { + GetDictionaries().GetOrDefault(cultureName)?.Fill(dictionary); + } + + public virtual LocalizedString GetOrNull(string cultureName, string name) + { + return GetDictionaries().GetOrDefault(cultureName)?.GetOrNull(name); + } + + protected virtual Dictionary GetDictionaries() + { + return _options.LocalizationDictionary + .GetOrAdd(_resourceName, () => new Dictionary()); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/ILocalizationDispatcher.cs b/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/ILocalizationDispatcher.cs deleted file mode 100644 index 13f3d5924..000000000 --- a/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/ILocalizationDispatcher.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Threading.Tasks; - -namespace LINGYUN.Abp.Localization.Dynamic -{ - internal interface ILocalizationDispatcher - { - /// - /// 发布变更事件 - /// - /// - /// - Task DispatchAsync(LocalizedStringCacheResetEventData data); - } -} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/ILocalizationSubscriber.cs b/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/ILocalizationSubscriber.cs deleted file mode 100644 index eefae487a..000000000 --- a/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/ILocalizationSubscriber.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Threading.Tasks; - -namespace LINGYUN.Abp.Localization.Dynamic -{ - /// - /// 本地化资源订阅 - /// - internal interface ILocalizationSubscriber - { - /// - /// 订阅变更事件 - /// - /// - void Subscribe(Func func); - } -} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/LocalizationDictionary.cs b/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/LocalizationDictionary.cs new file mode 100644 index 000000000..8335d9652 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/LocalizationDictionary.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using Volo.Abp.Localization; + +namespace LINGYUN.Abp.Localization.Dynamic +{ + public class LocalizationDictionary : Dictionary> + { + + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/LocalizationResetSynchronizer.cs b/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/LocalizationResetSynchronizer.cs index 9fd5acef2..02debd31e 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/LocalizationResetSynchronizer.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/LocalizationResetSynchronizer.cs @@ -1,23 +1,72 @@ -using System.Threading.Tasks; -using Volo.Abp.DependencyInjection; -using Volo.Abp.EventBus.Distributed; - -namespace LINGYUN.Abp.Localization.Dynamic -{ - internal class LocalizationResetSynchronizer : - IDistributedEventHandler, - ITransientDependency - { - private readonly ILocalizationDispatcher _dispatcher; - - public LocalizationResetSynchronizer( - ILocalizationDispatcher dispatcher) - { - _dispatcher = dispatcher; - } - public async Task HandleEventAsync(LocalizedStringCacheResetEventData eventData) - { - await _dispatcher.DispatchAsync(eventData); - } - } -} +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.EventBus.Distributed; +using Volo.Abp.Localization; + +namespace LINGYUN.Abp.Localization.Dynamic +{ + internal class LocalizationResetSynchronizer : + IDistributedEventHandler, + ITransientDependency + { + private readonly AbpLocalizationDynamicOptions _options; + + public LocalizationResetSynchronizer( + IOptions options) + { + _options = options.Value; + } + public virtual Task HandleEventAsync(LocalizedStringCacheResetEventData eventData) + { + var dictionaries = GetDictionaries(eventData.ResourceName); + if (!dictionaries.ContainsKey(eventData.CultureName)) + { + // TODO: 需要处理 data.Key data.Value 空引用 + var dictionary = new Dictionary(); + dictionary.Add(eventData.Key, new LocalizedString(eventData.Key, eventData.Value.NormalizeLineEndings())); + var newLocalizationDictionary = new StaticLocalizationDictionary(eventData.CultureName, dictionary); + + dictionaries.Add(eventData.CultureName, newLocalizationDictionary); + } + else + { + // 取出当前的缓存写入到新字典进行处理 + var nowLocalizationDictionary = dictionaries[eventData.CultureName]; + var dictionary = new Dictionary(); + nowLocalizationDictionary.Fill(dictionary); + + var existsKey = dictionary.ContainsKey(eventData.Key); + if (!existsKey) + { + // 如果不存在,则新增 + dictionary.Add(eventData.Key, new LocalizedString(eventData.Key, eventData.Value.NormalizeLineEndings())); + } + else if (existsKey && eventData.IsDeleted) + { + // 如果删掉了本地化的节点,删掉当前的缓存 + dictionary.Remove(eventData.Key); + } + + var newLocalizationDictionary = new StaticLocalizationDictionary(eventData.CultureName, dictionary); + + if (newLocalizationDictionary != null) + { + // 重新赋值变更过的缓存 + dictionaries[eventData.CultureName] = newLocalizationDictionary; + } + } + + return Task.CompletedTask; + } + + protected virtual Dictionary GetDictionaries(string resourceName) + { + return _options.LocalizationDictionary + .GetOrAdd(resourceName, () => new Dictionary()); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/LocalizationSubscriber.cs b/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/LocalizationSubscriber.cs deleted file mode 100644 index 4b3bcc894..000000000 --- a/aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/LocalizationSubscriber.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Threading.Tasks; -using Volo.Abp.DependencyInjection; - -namespace LINGYUN.Abp.Localization.Dynamic -{ - [ExposeServices( - typeof(ILocalizationSubscriber), - typeof(ILocalizationDispatcher), - typeof(LocalizationSubscriber))] - internal class LocalizationSubscriber : ILocalizationSubscriber, ILocalizationDispatcher, ISingletonDependency - { - private Func _handler; - - public LocalizationSubscriber() - { - _handler = (d) => - { - return Task.CompletedTask; - }; - } - - public void Subscribe(Func func) - { - _handler += func; - } - - public virtual async Task DispatchAsync(LocalizedStringCacheResetEventData data) - { - await _handler(data); - } - } -} diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/FileValidater.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/FileValidater.cs new file mode 100644 index 000000000..dd28e42f6 --- /dev/null +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/FileValidater.cs @@ -0,0 +1,96 @@ +using LINGYUN.Abp.OssManagement.Localization; +using LINGYUN.Abp.OssManagement.Settings; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.Localization; +using System; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.DependencyInjection; +using Volo.Abp.IO; +using Volo.Abp.Settings; + +namespace LINGYUN.Abp.OssManagement +{ + public class FileValidater : IFileValidater, ISingletonDependency + { + private readonly IMemoryCache _cache; + private readonly ISettingProvider _settingProvider; + private readonly IServiceProvider _serviceProvider; + private readonly IStringLocalizer _stringLocalizer; + + public FileValidater( + IMemoryCache cache, + ISettingProvider settingProvider, + IServiceProvider serviceProvider, + IStringLocalizer stringLocalizer) + { + _cache = cache; + _settingProvider = settingProvider; + _serviceProvider = serviceProvider; + _stringLocalizer = stringLocalizer; + } + + public virtual async Task ValidationAsync(UploadFile input) + { + var validation = await GetByCacheItemAsync(); + if (validation.SizeLimit * 1024 * 1024 < input.TotalSize) + { + throw new UserFriendlyException(_stringLocalizer["UploadFileSizeBeyondLimit", validation.SizeLimit]); + } + var fileExtensionName = FileHelper.GetExtension(input.FileName); + if (!validation.AllowedExtensions + .Any(fe => fe.Equals(fileExtensionName, StringComparison.CurrentCultureIgnoreCase))) + { + throw new UserFriendlyException(_stringLocalizer["NotAllowedFileExtensionName", fileExtensionName]); + } + } + + protected virtual async Task GetByCacheItemAsync() + { + var fileValidation = _cache.Get(FileValidation.CacheKey); + if (fileValidation == null) + { + fileValidation = await GetBySettingAsync(); + _cache.Set(FileValidation.CacheKey, + fileValidation, + new MemoryCacheEntryOptions + { + AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(2) + }); + } + return fileValidation; + } + + protected virtual async Task GetBySettingAsync() + { + var fileSizeLimited = await _settingProvider + .GetAsync( + AbpOssManagementSettingNames.FileLimitLength, + AbpOssManagementSettingNames.DefaultFileLimitLength); + var fileAllowExtension = await _settingProvider + .GetOrDefaultAsync(AbpOssManagementSettingNames.AllowFileExtensions, _serviceProvider); + + return new FileValidation(fileSizeLimited, fileAllowExtension.Split(',')); + } + } + + public class FileValidation + { + public const string CacheKey = "Abp.OssManagement.FileValidation"; + public long SizeLimit { get; set; } + public string[] AllowedExtensions { get; set; } + public FileValidation() + { + + } + + public FileValidation( + long sizeLimit, + string[] allowedExtensions) + { + SizeLimit = sizeLimit; + AllowedExtensions = allowedExtensions; + } + } +} diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/PublicFileAppService.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/PublicFileAppService.cs new file mode 100644 index 000000000..4473a1b96 --- /dev/null +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/PublicFileAppService.cs @@ -0,0 +1,89 @@ +using LINGYUN.Abp.Features.LimitValidation; +using LINGYUN.Abp.OssManagement.Features; +using Microsoft.AspNetCore.Authorization; +using System.IO; +using System.Threading.Tasks; +using System.Web; +using Volo.Abp; +using Volo.Abp.Features; +using Volo.Abp.Users; + +namespace LINGYUN.Abp.OssManagement +{ + /// + /// 所有登录用户公开访问文件服务接口 + /// bucket限制在users + /// path限制在用户id + /// + [Authorize] + // 不对外公开,仅通过控制器调用 + [RemoteService(IsEnabled = false, IsMetadataEnabled = false)] + public class PublicFileAppService : OssManagementApplicationServiceBase, IPublicFileAppService + { + private readonly IFileValidater _fileValidater; + private readonly IOssContainerFactory _ossContainerFactory; + + public PublicFileAppService( + IFileValidater fileValidater, + IOssContainerFactory ossContainerFactory) + { + _fileValidater = fileValidater; + _ossContainerFactory = ossContainerFactory; + } + + [RequiresFeature(AbpOssManagementFeatureNames.OssObject.UploadFile)] + [RequiresLimitFeature( + AbpOssManagementFeatureNames.OssObject.UploadLimit, + AbpOssManagementFeatureNames.OssObject.UploadInterval, + LimitPolicy.Month)] + public virtual async Task UploadAsync(UploadPublicFileInput input) + { + await _fileValidater.ValidationAsync(new UploadFile + { + TotalSize = input.Content.Length, + FileName = input.Object + }); + + var oss = _ossContainerFactory.Create(); + + var createOssObjectRequest = new CreateOssObjectRequest( + "users", + HttpUtility.UrlDecode(input.Object), + input.Content, + GetCurrentUserPath(HttpUtility.UrlDecode(input.Path))) + { + Overwrite = input.Overwrite + }; + + var ossObject = await oss.CreateObjectAsync(createOssObjectRequest); + + return ObjectMapper.Map(ossObject); + } + + [RequiresFeature(AbpOssManagementFeatureNames.OssObject.DownloadFile)] + [RequiresLimitFeature( + AbpOssManagementFeatureNames.OssObject.DownloadLimit, + AbpOssManagementFeatureNames.OssObject.DownloadInterval, + LimitPolicy.Month)] + public virtual async Task GetAsync(GetPublicFileInput input) + { + var ossObjectRequest = new GetOssObjectRequest( + "users", // 需要处理特殊字符 + HttpUtility.UrlDecode(input.Name), + GetCurrentUserPath(HttpUtility.UrlDecode(input.Path)), + HttpUtility.UrlDecode(input.Process)); + + var ossContainer = _ossContainerFactory.Create(); + var ossObject = await ossContainer.GetObjectAsync(ossObjectRequest); + + return ossObject.Content; + } + + private string GetCurrentUserPath(string path) + { + path = path.StartsWith("/") ? path.Substring(1) : path; + var userId = CurrentUser.GetId().ToString(); + return path.StartsWith(userId) ? path : $"{userId}/{path}"; + } + } +} diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Features/AbpOssManagementFeatureDefinitionProvider.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Features/AbpOssManagementFeatureDefinitionProvider.cs new file mode 100644 index 000000000..df5aa95b1 --- /dev/null +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Features/AbpOssManagementFeatureDefinitionProvider.cs @@ -0,0 +1,75 @@ +using LINGYUN.Abp.OssManagement.Localization; +using Volo.Abp.Features; +using Volo.Abp.Localization; +using Volo.Abp.Validation.StringValues; + +namespace LINGYUN.Abp.OssManagement.Features +{ + public class AbpOssManagementFeatureDefinitionProvider : FeatureDefinitionProvider + { + public override void Define(IFeatureDefinitionContext context) + { + var featureGroup = context.AddGroup( + name: AbpOssManagementFeatureNames.GroupName, + displayName: L("Features:OssManagement")); + + var ossFeature = featureGroup.AddFeature( + name: AbpOssManagementFeatureNames.OssObject.Default, + defaultValue: true.ToString(), + displayName: L("Features:DisplayName:OssObject"), + description: L("Features:Description:OssObject"), + valueType: new ToggleStringValueType(new BooleanValueValidator())); + + ossFeature.CreateChild( + name: AbpOssManagementFeatureNames.OssObject.DownloadFile, + defaultValue: false.ToString(), + displayName: L("Features:DisplayName:DownloadFile"), + description: L("Features:Description:DownloadFile"), + valueType: new ToggleStringValueType(new BooleanValueValidator())); + ossFeature.CreateChild( + name: AbpOssManagementFeatureNames.OssObject.DownloadLimit, + defaultValue: "1000", + displayName: L("Features:DisplayName:DownloadLimit"), + description: L("Features:Description:DownloadLimit"), + valueType: new FreeTextStringValueType(new NumericValueValidator(0, 100_0000))); // 上限100万次调用 + ossFeature.CreateChild( + name: AbpOssManagementFeatureNames.OssObject.DownloadInterval, + defaultValue: "1", + displayName: L("Features:DisplayName:DownloadInterval"), + description: L("Features:Description:DownloadInterval"), + valueType: new FreeTextStringValueType(new NumericValueValidator(1, 12))); // 上限12月 + + ossFeature.CreateChild( + name: AbpOssManagementFeatureNames.OssObject.UploadFile, + defaultValue: true.ToString(), + displayName: L("Features:DisplayName:UploadFile"), + description: L("Features:Description:UploadFile"), + valueType: new ToggleStringValueType(new BooleanValueValidator())); + ossFeature.CreateChild( + name: AbpOssManagementFeatureNames.OssObject.UploadLimit, + defaultValue: "1000", + displayName: L("Features:DisplayName:UploadLimit"), + description: L("Features:Description:UploadLimit"), + valueType: new FreeTextStringValueType(new NumericValueValidator(0, 100_0000))); // 上限100万次调用 + ossFeature.CreateChild( + name: AbpOssManagementFeatureNames.OssObject.UploadInterval, + defaultValue: "1", + displayName: L("Features:DisplayName:UploadInterval"), + description: L("Features:Description:UploadInterval"), + valueType: new FreeTextStringValueType(new NumericValueValidator(1, 12))); // 上限12月 + + // TODO: 此功能需要控制器协同,暂时不实现 + //fileSystemFeature.CreateChild( + // name: AbpOssManagementFeatureNames.OssObject.MaxUploadFileCount, + // defaultValue: 1.ToString(), + // displayName: L("Features:DisplayName:MaxUploadFileCount"), + // description: L("Features:Description:MaxUploadFileCount"), + // valueType: new FreeTextStringValueType(new NumericValueValidator(1, 10))); + } + + protected ILocalizableString L(string name) + { + return LocalizableString.Create(name); + } + } +} diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Features/AbpOssManagementFeatureNames.cs b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Features/AbpOssManagementFeatureNames.cs new file mode 100644 index 000000000..4d0ee0b35 --- /dev/null +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Features/AbpOssManagementFeatureNames.cs @@ -0,0 +1,41 @@ +namespace LINGYUN.Abp.OssManagement.Features +{ + public class AbpOssManagementFeatureNames + { + public const string GroupName = "AbpOssManagement"; + + + public class OssObject + { + public const string Default = GroupName + ".OssObject"; + /// + /// 下载文件功能 + /// + public const string DownloadFile = Default + ".DownloadFile"; + /// + /// 下载文件功能限制次数 + /// + public const string DownloadLimit = Default + ".DownloadLimit"; + /// + /// 下载文件功能限制次数周期 + /// + public const string DownloadInterval = Default + ".DownloadInterval"; + /// + /// 上传文件功能 + /// + public const string UploadFile = Default + ".UploadFile"; + /// + /// 上传文件功能限制次数 + /// + public const string UploadLimit = Default + ".UploadLimit"; + /// + /// 上传文件功能限制次数周期 + /// + public const string UploadInterval = Default + ".UploadInterval"; + /// + /// 最大上传文件 + /// + public const string MaxUploadFileCount = Default + ".MaxUploadFileCount"; + } + } +} diff --git a/aspnet-core/services/localization/LINGYUN.Abp.LocalizationManagement.HttpApi.Host/Properties/launchSettings.json b/aspnet-core/services/localization/LINGYUN.Abp.LocalizationManagement.HttpApi.Host/Properties/launchSettings.json index 26215d352..3c7dbbca2 100644 --- a/aspnet-core/services/localization/LINGYUN.Abp.LocalizationManagement.HttpApi.Host/Properties/launchSettings.json +++ b/aspnet-core/services/localization/LINGYUN.Abp.LocalizationManagement.HttpApi.Host/Properties/launchSettings.json @@ -1,21 +1,21 @@ -{ - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:30030", - "sslPort": 0 - } - }, - "profiles": { - "LINGYUN.Abp.LocalizationManagement.HttpApi.Host": { - "commandName": "Project", - "dotnetRunMessages": "true", - "launchBrowser": false, - "applicationUrl": "http://0.0.0.0:30030", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:30030", + "sslPort": 0 + } + }, + "profiles": { + "LINGYUN.Abp.LocalizationManagement.HttpApi.Host": { + "commandName": "Project", + "dotnetRunMessages": "true", + "launchBrowser": false, + "applicationUrl": "http://0.0.0.0:30030", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +}