Browse Source

Merge pull request #327 from colinin/4.4

dynamically localized resources are initialized at startup time
pull/364/head
yx lin 4 years ago
committed by GitHub
parent
commit
65c100ee24
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 31
      aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/AbpLocalizationDynamicModule.cs
  2. 22
      aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/AbpLocalizationDynamicOptions.cs
  3. 45
      aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/DynamicLocalizationInitializeService.cs
  4. 161
      aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/DynamicLocalizationResourceContributor.cs
  5. 14
      aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/ILocalizationDispatcher.cs
  6. 17
      aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/ILocalizationSubscriber.cs
  7. 10
      aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/LocalizationDictionary.cs
  8. 95
      aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/LocalizationResetSynchronizer.cs
  9. 33
      aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/LocalizationSubscriber.cs
  10. 739
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Aliyun/LINGYUN/Abp/OssManagement/Aliyun/AliyunOssContainer.cs
  11. 4
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN.Abp.OssManagement.Application.Contracts.csproj
  12. 24
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/AbpOssManagementApplicationContractsModule.cs
  13. 5
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN.Abp.OssManagement.Application.csproj
  14. 50
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/AbpOssManagementApplicationModule.cs
  15. 2
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/FileValidater.cs
  16. 28
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssManagementApplicationServiceBase.cs
  17. 217
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssObjectAppService.cs
  18. 16
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/PublicFileAppService.cs
  19. 5
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN.Abp.OssManagement.Domain.Shared.csproj
  20. 72
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/AbpOssManagementDomainSharedModule.cs
  21. 0
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Features/AbpOssManagementFeatureDefinitionProvider.cs
  22. 82
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Features/AbpOssManagementFeatureNames.cs
  23. 1
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Localization/Resources/en.json
  24. 1
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Localization/Resources/zh-Hans.json
  25. 35
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/OssManagementErrorCodes.cs
  26. 49
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain/LINGYUN/Abp/OssManagement/AbpOssManagementDomainModule.cs
  27. 36
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.FileSystem/LINGYUN/Abp/OssManagement/FileSystem/AbpOssManagementFileSystemModule.cs
  28. 15
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.FileSystem/LINGYUN/Abp/OssManagement/FileSystem/FileSystemOssContainer.cs
  29. 96
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.FileSystem/LINGYUN/Abp/OssManagement/FileSystem/FileSystemOssContainerFactory.cs
  30. 1
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN.Abp.OssManagement.HttpApi.csproj
  31. 68
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/AbpOssManagementHttpApiModule.cs
  32. 9
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/IFileValidater.cs
  33. 4
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/StaticFilesController.cs
  34. 12
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/UploadOssObjectInput.cs
  35. 20
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.SettingManagement/AbpOssManagementSettingManagementModule.cs
  36. 101
      aspnet-core/modules/oss-management/README.md
  37. 42
      aspnet-core/services/localization/LINGYUN.Abp.LocalizationManagement.HttpApi.Host/Properties/launchSettings.json
  38. 675
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/AppPlatformHttpApiHostModule.cs

31
aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/AbpLocalizationDynamicModule.cs

@ -1,13 +1,18 @@
using Volo.Abp.EventBus; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Localization; using Volo.Abp.EventBus;
using Volo.Abp.Modularity; using Volo.Abp.Localization;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Localization.Dynamic
{ namespace LINGYUN.Abp.Localization.Dynamic
[DependsOn( {
typeof(AbpEventBusModule), [DependsOn(
typeof(AbpLocalizationModule))] typeof(AbpEventBusModule),
public class AbpLocalizationDynamicModule : AbpModule typeof(AbpLocalizationModule))]
{ public class AbpLocalizationDynamicModule : AbpModule
} {
} public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddHostedService<DynamicLocalizationInitializeService>();
}
}
}

22
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<string, ILocalizationDictionary> dictionares)
{
var _dictionares = LocalizationDictionary
.GetOrAdd(resourceName, () => new Dictionary<string, ILocalizationDictionary>());
_dictionares.AddIfNotContains(dictionares);
}
}
}

45
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<AbpLocalizationOptions> localizationOptions,
IOptions<AbpLocalizationDynamicOptions> 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;
}
}
}

161
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.DependencyInjection;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options;
using Nito.AsyncEx; using System.Collections.Generic;
using System; using Volo.Abp.Localization;
using System.Collections.Generic;
using System.Threading.Tasks; namespace LINGYUN.Abp.Localization.Dynamic
using Volo.Abp.Localization; {
using Volo.Abp.Threading; public class DynamicLocalizationResourceContributor : ILocalizationResourceContributor
{
namespace LINGYUN.Abp.Localization.Dynamic private readonly string _resourceName;
{
public class DynamicLocalizationResourceContributor : ILocalizationResourceContributor private AbpLocalizationDynamicOptions _options;
{
private ILogger _logger; public DynamicLocalizationResourceContributor(string resourceName)
private ILocalizationSubscriber _subscriber; {
_resourceName = resourceName;
private ILocalizationStore _store; }
protected ILocalizationStore Store => _store;
public virtual void Initialize(LocalizationResourceInitializationContext context)
private Dictionary<string, ILocalizationDictionary> _dictionaries; {
_options = context.ServiceProvider.GetService<IOptions<AbpLocalizationDynamicOptions>>().Value;
private readonly string _resourceName; }
private readonly AsyncLock _asyncLock = new AsyncLock();
public virtual void Fill(string cultureName, Dictionary<string, LocalizedString> dictionary)
public DynamicLocalizationResourceContributor(string resourceName) {
{ GetDictionaries().GetOrDefault(cultureName)?.Fill(dictionary);
_resourceName = resourceName; }
}
public virtual LocalizedString GetOrNull(string cultureName, string name)
public virtual void Initialize(LocalizationResourceInitializationContext context) {
{ return GetDictionaries().GetOrDefault(cultureName)?.GetOrNull(name);
_logger = context.ServiceProvider.GetService<ILogger<DynamicLocalizationResourceContributor>>(); }
_store = context.ServiceProvider.GetRequiredService<ILocalizationStore>(); protected virtual Dictionary<string, ILocalizationDictionary> GetDictionaries()
_subscriber = context.ServiceProvider.GetRequiredService<ILocalizationSubscriber>(); {
_subscriber.Subscribe(OnChanged); return _options.LocalizationDictionary
} .GetOrAdd(_resourceName, () => new Dictionary<string, ILocalizationDictionary>());
}
public virtual void Fill(string cultureName, Dictionary<string, LocalizedString> dictionary) }
{ }
GetDictionaries().GetOrDefault(cultureName)?.Fill(dictionary);
}
public virtual LocalizedString GetOrNull(string cultureName, string name)
{
return GetDictionaries().GetOrDefault(cultureName)?.GetOrNull(name);
}
protected virtual Dictionary<string, ILocalizationDictionary> 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<string, LocalizedString>();
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<string, LocalizedString>();
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;
}
}
}

14
aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/ILocalizationDispatcher.cs

@ -1,14 +0,0 @@
using System.Threading.Tasks;
namespace LINGYUN.Abp.Localization.Dynamic
{
internal interface ILocalizationDispatcher
{
/// <summary>
/// 发布变更事件
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
Task DispatchAsync(LocalizedStringCacheResetEventData data);
}
}

17
aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/ILocalizationSubscriber.cs

@ -1,17 +0,0 @@
using System;
using System.Threading.Tasks;
namespace LINGYUN.Abp.Localization.Dynamic
{
/// <summary>
/// 本地化资源订阅
/// </summary>
internal interface ILocalizationSubscriber
{
/// <summary>
/// 订阅变更事件
/// </summary>
/// <param name="func"></param>
void Subscribe(Func<LocalizedStringCacheResetEventData, Task> func);
}
}

10
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<string, Dictionary<string, ILocalizationDictionary>>
{
}
}

95
aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/LocalizationResetSynchronizer.cs

@ -1,23 +1,72 @@
using System.Threading.Tasks; using Microsoft.Extensions.Localization;
using Volo.Abp.DependencyInjection; using Microsoft.Extensions.Options;
using Volo.Abp.EventBus.Distributed; using System;
using System.Collections.Generic;
namespace LINGYUN.Abp.Localization.Dynamic using System.Threading.Tasks;
{ using Volo.Abp.DependencyInjection;
internal class LocalizationResetSynchronizer : using Volo.Abp.EventBus.Distributed;
IDistributedEventHandler<LocalizedStringCacheResetEventData>, using Volo.Abp.Localization;
ITransientDependency
{ namespace LINGYUN.Abp.Localization.Dynamic
private readonly ILocalizationDispatcher _dispatcher; {
internal class LocalizationResetSynchronizer :
public LocalizationResetSynchronizer( IDistributedEventHandler<LocalizedStringCacheResetEventData>,
ILocalizationDispatcher dispatcher) ITransientDependency
{ {
_dispatcher = dispatcher; private readonly AbpLocalizationDynamicOptions _options;
}
public async Task HandleEventAsync(LocalizedStringCacheResetEventData eventData) public LocalizationResetSynchronizer(
{ IOptions<AbpLocalizationDynamicOptions> options)
await _dispatcher.DispatchAsync(eventData); {
} _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<string, LocalizedString>();
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<string, LocalizedString>();
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<string, ILocalizationDictionary> GetDictionaries(string resourceName)
{
return _options.LocalizationDictionary
.GetOrAdd(resourceName, () => new Dictionary<string, ILocalizationDictionary>());
}
}
}

33
aspnet-core/modules/common/LINGYUN.Abp.Localization.Dynamic/LINGYUN/Abp/Localization/Dynamic/LocalizationSubscriber.cs

@ -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<LocalizedStringCacheResetEventData, Task> _handler;
public LocalizationSubscriber()
{
_handler = (d) =>
{
return Task.CompletedTask;
};
}
public void Subscribe(Func<LocalizedStringCacheResetEventData, Task> func)
{
_handler += func;
}
public virtual async Task DispatchAsync(LocalizedStringCacheResetEventData data)
{
await _handler(data);
}
}
}

739
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Aliyun/LINGYUN/Abp/OssManagement/Aliyun/AliyunOssContainer.cs

@ -1,369 +1,370 @@
using Aliyun.OSS; using Aliyun.OSS;
using LINGYUN.Abp.BlobStoring.Aliyun; using LINGYUN.Abp.BlobStoring.Aliyun;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.OssManagement.Aliyun namespace LINGYUN.Abp.OssManagement.Aliyun
{ {
/// <summary> /// <summary>
/// Oss容器的阿里云实现 /// Oss容器的阿里云实现
/// </summary> /// </summary>
internal class AliyunOssContainer : IOssContainer internal class AliyunOssContainer : IOssContainer
{ {
protected ICurrentTenant CurrentTenant { get; } protected ICurrentTenant CurrentTenant { get; }
protected IOssClientFactory OssClientFactory { get; } protected IOssClientFactory OssClientFactory { get; }
public AliyunOssContainer( public AliyunOssContainer(
ICurrentTenant currentTenant, ICurrentTenant currentTenant,
IOssClientFactory ossClientFactory) IOssClientFactory ossClientFactory)
{ {
CurrentTenant = currentTenant; CurrentTenant = currentTenant;
OssClientFactory = ossClientFactory; OssClientFactory = ossClientFactory;
} }
public virtual async Task BulkDeleteObjectsAsync(BulkDeleteObjectRequest request) public virtual async Task BulkDeleteObjectsAsync(BulkDeleteObjectRequest request)
{ {
var ossClient = await CreateClientAsync(); var ossClient = await CreateClientAsync();
var path = GetBasePath(request.Path); var path = GetBasePath(request.Path);
var aliyunRequest = new DeleteObjectsRequest(request.Bucket, request.Objects.Select(x => x += path).ToList()); var aliyunRequest = new DeleteObjectsRequest(request.Bucket, request.Objects.Select(x => x += path).ToList());
ossClient.DeleteObjects(aliyunRequest); ossClient.DeleteObjects(aliyunRequest);
} }
public virtual async Task<OssContainer> CreateAsync(string name) public virtual async Task<OssContainer> CreateAsync(string name)
{ {
var ossClient = await CreateClientAsync(); var ossClient = await CreateClientAsync();
if (BucketExists(ossClient, name)) if (BucketExists(ossClient, name))
{ {
throw new BusinessException(code: OssManagementErrorCodes.ContainerAlreadyExists); throw new BusinessException(code: OssManagementErrorCodes.ContainerAlreadyExists);
} }
var bucket = ossClient.CreateBucket(name); var bucket = ossClient.CreateBucket(name);
return new OssContainer( return new OssContainer(
bucket.Name, bucket.Name,
bucket.CreationDate, bucket.CreationDate,
0L, 0L,
bucket.CreationDate, bucket.CreationDate,
new Dictionary<string, string> new Dictionary<string, string>
{ {
{ "Id", bucket.Owner?.Id }, { "Id", bucket.Owner?.Id },
{ "DisplayName", bucket.Owner?.DisplayName } { "DisplayName", bucket.Owner?.DisplayName }
}); });
} }
public virtual async Task<OssObject> CreateObjectAsync(CreateOssObjectRequest request) public virtual async Task<OssObject> CreateObjectAsync(CreateOssObjectRequest request)
{ {
var ossClient = await CreateClientAsync(); var ossClient = await CreateClientAsync();
var objectPath = GetBasePath(request.Path); var objectPath = GetBasePath(request.Path);
var objectName = objectPath.IsNullOrWhiteSpace() var objectName = objectPath.IsNullOrWhiteSpace()
? request.Object ? request.Object
: objectPath + request.Object; : objectPath + request.Object;
if (!request.Overwrite && ObjectExists(ossClient, request.Bucket, objectName)) if (!request.Overwrite && ObjectExists(ossClient, request.Bucket, objectName))
{ {
throw new BusinessException(code: OssManagementErrorCodes.ObjectAlreadyExists); throw new BusinessException(code: OssManagementErrorCodes.ObjectAlreadyExists);
} }
// 当一个对象名称是以 / 结尾时,不论该对象是否存有数据,都以目录的形式存在 // 当一个对象名称是以 / 结尾时,不论该对象是否存有数据,都以目录的形式存在
// 详情见:https://help.aliyun.com/document_detail/31910.html // 详情见:https://help.aliyun.com/document_detail/31910.html
if (objectName.EndsWith("/") && if (objectName.EndsWith("/") &&
request.Content.IsNullOrEmpty()) request.Content.IsNullOrEmpty())
{ {
var emptyStream = new MemoryStream(); var emptyStream = new MemoryStream();
var emptyData = System.Text.Encoding.UTF8.GetBytes(""); var emptyData = System.Text.Encoding.UTF8.GetBytes("");
await emptyStream.WriteAsync(emptyData, 0, emptyData.Length); await emptyStream.WriteAsync(emptyData, 0, emptyData.Length);
request.SetContent(emptyStream); request.SetContent(emptyStream);
} }
// 没有bucket则创建 // 没有bucket则创建
if (!BucketExists(ossClient, request.Bucket)) if (!BucketExists(ossClient, request.Bucket))
{ {
ossClient.CreateBucket(request.Bucket); ossClient.CreateBucket(request.Bucket);
} }
var aliyunObjectRequest = new PutObjectRequest(request.Bucket, objectName, request.Content) var aliyunObjectRequest = new PutObjectRequest(request.Bucket, objectName, request.Content)
{ {
Metadata = new ObjectMetadata() Metadata = new ObjectMetadata()
}; };
if (request.ExpirationTime.HasValue) if (request.ExpirationTime.HasValue)
{ {
aliyunObjectRequest.Metadata.ExpirationTime = DateTime.Now.Add(request.ExpirationTime.Value); aliyunObjectRequest.Metadata.ExpirationTime = DateTime.Now.Add(request.ExpirationTime.Value);
} }
var aliyunObject = ossClient.PutObject(aliyunObjectRequest); var aliyunObject = ossClient.PutObject(aliyunObjectRequest);
var ossObject = new OssObject( var ossObject = new OssObject(
!objectPath.IsNullOrWhiteSpace() !objectPath.IsNullOrWhiteSpace()
? objectName.Replace(objectPath, "") ? objectName.Replace(objectPath, "")
: objectName, : objectName,
objectPath, objectPath,
DateTime.Now, DateTime.Now,
aliyunObject.ContentLength, aliyunObject.ContentLength,
DateTime.Now, DateTime.Now,
aliyunObject.ResponseMetadata, aliyunObject.ResponseMetadata,
objectName.EndsWith("/") // 名称结尾是 / 符号的则为目录:https://help.aliyun.com/document_detail/31910.html objectName.EndsWith("/") // 名称结尾是 / 符号的则为目录:https://help.aliyun.com/document_detail/31910.html
) )
{ {
FullName = objectName FullName = objectName
}; };
if (!Equals(request.Content, Stream.Null)) if (!Equals(request.Content, Stream.Null))
{ {
request.Content.Seek(0, SeekOrigin.Begin); request.Content.Seek(0, SeekOrigin.Begin);
ossObject.SetContent(request.Content); ossObject.SetContent(request.Content);
} }
return ossObject; return ossObject;
} }
public virtual async Task DeleteAsync(string name) public virtual async Task DeleteAsync(string name)
{ {
var ossClient = await CreateClientAsync(); // 阿里云oss在控制台设置即可,无需改变
var ossClient = await CreateClientAsync();
if (BucketExists(ossClient, name))
{ if (BucketExists(ossClient, name))
ossClient.DeleteBucket(name); {
} ossClient.DeleteBucket(name);
} }
}
public virtual async Task DeleteObjectAsync(GetOssObjectRequest request)
{ public virtual async Task DeleteObjectAsync(GetOssObjectRequest request)
var ossClient = await CreateClientAsync(); {
var ossClient = await CreateClientAsync();
var objectPath = GetBasePath(request.Path);
var objectPath = GetBasePath(request.Path);
var objectName = objectPath.IsNullOrWhiteSpace()
? request.Object var objectName = objectPath.IsNullOrWhiteSpace()
: objectPath + request.Object; ? request.Object
: objectPath + request.Object;
if (BucketExists(ossClient, request.Bucket) &&
ObjectExists(ossClient, request.Bucket, objectName)) if (BucketExists(ossClient, request.Bucket) &&
{ ObjectExists(ossClient, request.Bucket, objectName))
var objectListing = ossClient.ListObjects(request.Bucket, objectName); {
if (objectListing.CommonPrefixes.Any() || var objectListing = ossClient.ListObjects(request.Bucket, objectName);
objectListing.ObjectSummaries.Any()) if (objectListing.CommonPrefixes.Any() ||
{ objectListing.ObjectSummaries.Any())
throw new BusinessException(code: OssManagementErrorCodes.ObjectDeleteWithNotEmpty); {
// throw new ObjectDeleteWithNotEmptyException("00201", $"Can't not delete oss object {request.Object}, because it is not empty!"); throw new BusinessException(code: OssManagementErrorCodes.ObjectDeleteWithNotEmpty);
} // throw new ObjectDeleteWithNotEmptyException("00201", $"Can't not delete oss object {request.Object}, because it is not empty!");
ossClient.DeleteObject(request.Bucket, objectName); }
} ossClient.DeleteObject(request.Bucket, objectName);
} }
}
public virtual async Task<bool> ExistsAsync(string name)
{ public virtual async Task<bool> ExistsAsync(string name)
var ossClient = await CreateClientAsync(); {
var ossClient = await CreateClientAsync();
return BucketExists(ossClient, name);
} return BucketExists(ossClient, name);
}
public virtual async Task<OssContainer> GetAsync(string name)
{ public virtual async Task<OssContainer> GetAsync(string name)
var ossClient = await CreateClientAsync(); {
if (!BucketExists(ossClient, name)) var ossClient = await CreateClientAsync();
{ if (!BucketExists(ossClient, name))
throw new BusinessException(code: OssManagementErrorCodes.ContainerNotFound); {
// throw new ContainerNotFoundException($"Can't not found container {name} in aliyun blob storing"); throw new BusinessException(code: OssManagementErrorCodes.ContainerNotFound);
} // throw new ContainerNotFoundException($"Can't not found container {name} in aliyun blob storing");
var bucket = ossClient.GetBucketInfo(name); }
var bucket = ossClient.GetBucketInfo(name);
return new OssContainer(
bucket.Bucket.Name, return new OssContainer(
bucket.Bucket.CreationDate, bucket.Bucket.Name,
0L, bucket.Bucket.CreationDate,
bucket.Bucket.CreationDate, 0L,
new Dictionary<string, string> bucket.Bucket.CreationDate,
{ new Dictionary<string, string>
{ "Id", bucket.Bucket.Owner?.Id }, {
{ "DisplayName", bucket.Bucket.Owner?.DisplayName } { "Id", bucket.Bucket.Owner?.Id },
}); { "DisplayName", bucket.Bucket.Owner?.DisplayName }
} });
}
public virtual async Task<OssObject> GetObjectAsync(GetOssObjectRequest request)
{ public virtual async Task<OssObject> GetObjectAsync(GetOssObjectRequest request)
var ossClient = await CreateClientAsync(); {
if (!BucketExists(ossClient, request.Bucket)) var ossClient = await CreateClientAsync();
{ if (!BucketExists(ossClient, request.Bucket))
throw new BusinessException(code: OssManagementErrorCodes.ContainerNotFound); {
// throw new ContainerNotFoundException($"Can't not found container {request.Bucket} in aliyun blob storing"); throw new BusinessException(code: OssManagementErrorCodes.ContainerNotFound);
} // throw new ContainerNotFoundException($"Can't not found container {request.Bucket} in aliyun blob storing");
}
var objectPath = GetBasePath(request.Path);
var objectName = objectPath.IsNullOrWhiteSpace() var objectPath = GetBasePath(request.Path);
? request.Object var objectName = objectPath.IsNullOrWhiteSpace()
: objectPath + request.Object; ? request.Object
: objectPath + request.Object;
if (!ObjectExists(ossClient, request.Bucket, objectName))
{ if (!ObjectExists(ossClient, request.Bucket, objectName))
throw new BusinessException(code: OssManagementErrorCodes.ObjectNotFound); {
// throw new ContainerNotFoundException($"Can't not found object {objectName} in container {request.Bucket} with aliyun blob storing"); throw new BusinessException(code: OssManagementErrorCodes.ObjectNotFound);
} // throw new ContainerNotFoundException($"Can't not found object {objectName} in container {request.Bucket} with aliyun blob storing");
}
var aliyunOssObjectRequest = new GetObjectRequest(request.Bucket, objectName, request.Process);
var aliyunOssObject = ossClient.GetObject(aliyunOssObjectRequest); var aliyunOssObjectRequest = new GetObjectRequest(request.Bucket, objectName, request.Process);
var ossObject = new OssObject( var aliyunOssObject = ossClient.GetObject(aliyunOssObjectRequest);
!objectPath.IsNullOrWhiteSpace() var ossObject = new OssObject(
? aliyunOssObject.Key.Replace(objectPath, "") !objectPath.IsNullOrWhiteSpace()
: aliyunOssObject.Key, ? aliyunOssObject.Key.Replace(objectPath, "")
request.Path, : aliyunOssObject.Key,
aliyunOssObject.Metadata.LastModified, request.Path,
aliyunOssObject.Metadata.ContentLength, aliyunOssObject.Metadata.LastModified,
aliyunOssObject.Metadata.LastModified, aliyunOssObject.Metadata.ContentLength,
aliyunOssObject.Metadata.UserMetadata, aliyunOssObject.Metadata.LastModified,
aliyunOssObject.Key.EndsWith("/")) aliyunOssObject.Metadata.UserMetadata,
{ aliyunOssObject.Key.EndsWith("/"))
FullName = aliyunOssObject.Key {
}; FullName = aliyunOssObject.Key
};
if (aliyunOssObject.IsSetResponseStream())
{ if (aliyunOssObject.IsSetResponseStream())
var memoryStream = new MemoryStream(); {
await aliyunOssObject.Content.CopyToAsync(memoryStream); var memoryStream = new MemoryStream();
memoryStream.Seek(0, SeekOrigin.Begin); await aliyunOssObject.Content.CopyToAsync(memoryStream);
ossObject.SetContent(memoryStream); memoryStream.Seek(0, SeekOrigin.Begin);
} ossObject.SetContent(memoryStream);
}
return ossObject;
} return ossObject;
}
public virtual async Task<GetOssContainersResponse> GetListAsync(GetOssContainersRequest request)
{ public virtual async Task<GetOssContainersResponse> GetListAsync(GetOssContainersRequest request)
var ossClient = await CreateClientAsync(); {
var ossClient = await CreateClientAsync();
var aliyunRequest = new ListBucketsRequest
{ var aliyunRequest = new ListBucketsRequest
Marker = request.Marker, {
Prefix = request.Prefix, Marker = request.Marker,
MaxKeys = request.MaxKeys Prefix = request.Prefix,
}; MaxKeys = request.MaxKeys
var bucketsResponse = ossClient.ListBuckets(aliyunRequest); };
var bucketsResponse = ossClient.ListBuckets(aliyunRequest);
return new GetOssContainersResponse(
bucketsResponse.Prefix, return new GetOssContainersResponse(
bucketsResponse.Marker, bucketsResponse.Prefix,
bucketsResponse.NextMaker, bucketsResponse.Marker,
bucketsResponse.MaxKeys ?? 0, bucketsResponse.NextMaker,
bucketsResponse.Buckets bucketsResponse.MaxKeys ?? 0,
.Select(x => new OssContainer( bucketsResponse.Buckets
x.Name, .Select(x => new OssContainer(
x.CreationDate, x.Name,
0L, x.CreationDate,
x.CreationDate, 0L,
new Dictionary<string, string> x.CreationDate,
{ new Dictionary<string, string>
{ "Id", x.Owner?.Id }, {
{ "DisplayName", x.Owner?.DisplayName } { "Id", x.Owner?.Id },
})) { "DisplayName", x.Owner?.DisplayName }
.ToList()); }))
} .ToList());
}
public virtual async Task<GetOssObjectsResponse> GetObjectsAsync(GetOssObjectsRequest request)
{ public virtual async Task<GetOssObjectsResponse> GetObjectsAsync(GetOssObjectsRequest request)
{
var ossClient = await CreateClientAsync();
var ossClient = await CreateClientAsync();
var objectPath = GetBasePath(request.Prefix);
var marker = !objectPath.IsNullOrWhiteSpace() && !request.Marker.IsNullOrWhiteSpace() var objectPath = GetBasePath(request.Prefix);
? request.Marker.Replace(objectPath, "") var marker = !objectPath.IsNullOrWhiteSpace() && !request.Marker.IsNullOrWhiteSpace()
: request.Marker; ? request.Marker.Replace(objectPath, "")
var aliyunRequest = new ListObjectsRequest(request.BucketName) : request.Marker;
{ var aliyunRequest = new ListObjectsRequest(request.BucketName)
Marker = !marker.IsNullOrWhiteSpace() ? objectPath + marker : marker, {
Prefix = objectPath, Marker = !marker.IsNullOrWhiteSpace() ? objectPath + marker : marker,
MaxKeys = request.MaxKeys, Prefix = objectPath,
EncodingType = request.EncodingType, MaxKeys = request.MaxKeys,
Delimiter = request.Delimiter EncodingType = request.EncodingType,
}; Delimiter = request.Delimiter
var objectsResponse = ossClient.ListObjects(aliyunRequest); };
var objectsResponse = ossClient.ListObjects(aliyunRequest);
var ossObjects = objectsResponse.ObjectSummaries
.Where(x => !x.Key.Equals(objectsResponse.Prefix))// 过滤当前的目录返回值 var ossObjects = objectsResponse.ObjectSummaries
.Select(x => new OssObject( .Where(x => !x.Key.Equals(objectsResponse.Prefix))// 过滤当前的目录返回值
!objectPath.IsNullOrWhiteSpace() && !x.Key.Equals(objectPath) .Select(x => new OssObject(
? x.Key.Replace(objectPath, "") !objectPath.IsNullOrWhiteSpace() && !x.Key.Equals(objectPath)
: x.Key, // 去除目录名称 ? x.Key.Replace(objectPath, "")
request.Prefix, : x.Key, // 去除目录名称
x.LastModified, request.Prefix,
x.Size, x.LastModified,
x.LastModified, x.Size,
new Dictionary<string, string> x.LastModified,
{ new Dictionary<string, string>
{ "Id", x.Owner?.Id }, {
{ "DisplayName", x.Owner?.DisplayName } { "Id", x.Owner?.Id },
}, { "DisplayName", x.Owner?.DisplayName }
x.Key.EndsWith("/")) },
{ x.Key.EndsWith("/"))
FullName = x.Key {
}) FullName = x.Key
.ToList(); })
// 当 Delimiter 为 / 时, objectsResponse.CommonPrefixes 可用于代表层级目录 .ToList();
if (objectsResponse.CommonPrefixes.Any()) // 当 Delimiter 为 / 时, objectsResponse.CommonPrefixes 可用于代表层级目录
{ if (objectsResponse.CommonPrefixes.Any())
ossObjects.InsertRange(0, {
objectsResponse.CommonPrefixes ossObjects.InsertRange(0,
.Select(x => new OssObject( objectsResponse.CommonPrefixes
x.Replace(objectPath, ""), .Select(x => new OssObject(
request.Prefix, x.Replace(objectPath, ""),
null, request.Prefix,
0L, null,
null, 0L,
null, null,
true))); null,
} true)));
// 排序 }
// TODO: 是否需要客户端来排序 // 排序
ossObjects.Sort(new OssObjectComparer()); // TODO: 是否需要客户端来排序
ossObjects.Sort(new OssObjectComparer());
return new GetOssObjectsResponse(
objectsResponse.BucketName, return new GetOssObjectsResponse(
request.Prefix, objectsResponse.BucketName,
marker, request.Prefix,
!objectPath.IsNullOrWhiteSpace() && !objectsResponse.NextMarker.IsNullOrWhiteSpace() marker,
? objectsResponse.NextMarker.Replace(objectPath, "") !objectPath.IsNullOrWhiteSpace() && !objectsResponse.NextMarker.IsNullOrWhiteSpace()
: objectsResponse.NextMarker, ? objectsResponse.NextMarker.Replace(objectPath, "")
objectsResponse.Delimiter, : objectsResponse.NextMarker,
objectsResponse.MaxKeys, objectsResponse.Delimiter,
ossObjects); objectsResponse.MaxKeys,
} ossObjects);
}
protected virtual string GetBasePath(string path)
{ protected virtual string GetBasePath(string path)
string objectPath = ""; {
if (CurrentTenant.Id == null) string objectPath = "";
{ if (CurrentTenant.Id == null)
objectPath += "host/"; {
} objectPath += "host/";
else }
{ else
objectPath += "tenants/" + CurrentTenant.Id.Value.ToString("D"); {
} objectPath += "tenants/" + CurrentTenant.Id.Value.ToString("D");
}
objectPath += path ?? "";
objectPath += path ?? "";
return objectPath.EnsureEndsWith('/');
} return objectPath.EnsureEndsWith('/');
}
protected virtual bool BucketExists(IOss client, string bucketName)
{ protected virtual bool BucketExists(IOss client, string bucketName)
return client.DoesBucketExist(bucketName); {
} return client.DoesBucketExist(bucketName);
}
protected virtual bool ObjectExists(IOss client, string bucketName, string objectName)
{ protected virtual bool ObjectExists(IOss client, string bucketName, string objectName)
return client.DoesObjectExist(bucketName, objectName); {
} return client.DoesObjectExist(bucketName, objectName);
}
protected virtual async Task<IOss> CreateClientAsync()
{ protected virtual async Task<IOss> CreateClientAsync()
return await OssClientFactory.CreateAsync<AbpOssManagementContainer>(); {
} return await OssClientFactory.CreateAsync<AbpOssManagementContainer>();
} }
} }
}

4
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN.Abp.OssManagement.Application.Contracts.csproj

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
@ -8,7 +8,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application" Version="4.4.0" /> <PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="4.4.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

24
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/AbpOssManagementApplicationContractsModule.cs

@ -1,12 +1,12 @@
using Volo.Abp.Application; using Volo.Abp.Application;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
namespace LINGYUN.Abp.OssManagement namespace LINGYUN.Abp.OssManagement
{ {
[DependsOn( [DependsOn(
typeof(AbpOssManagementDomainSharedModule), typeof(AbpOssManagementDomainSharedModule),
typeof(AbpDddApplicationModule))] typeof(AbpDddApplicationContractsModule))]
public class AbpOssManagementApplicationContractsModule : AbpModule public class AbpOssManagementApplicationContractsModule : AbpModule
{ {
} }
} }

5
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN.Abp.OssManagement.Application.csproj

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
@ -9,9 +9,12 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.AutoMapper" Version="4.4.0" /> <PackageReference Include="Volo.Abp.AutoMapper" Version="4.4.0" />
<PackageReference Include="Volo.Abp.Ddd.Application" Version="4.4.0" />
<PackageReference Include="Volo.Abp.Caching" Version="4.4.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\common\LINGYUN.Abp.Settings\LINGYUN.Abp.Settings.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.OssManagement.Application.Contracts\LINGYUN.Abp.OssManagement.Application.Contracts.csproj" /> <ProjectReference Include="..\LINGYUN.Abp.OssManagement.Application.Contracts\LINGYUN.Abp.OssManagement.Application.Contracts.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.OssManagement.Domain\LINGYUN.Abp.OssManagement.Domain.csproj" /> <ProjectReference Include="..\LINGYUN.Abp.OssManagement.Domain\LINGYUN.Abp.OssManagement.Domain.csproj" />
</ItemGroup> </ItemGroup>

50
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/AbpOssManagementApplicationModule.cs

@ -1,23 +1,27 @@
using Volo.Abp.AutoMapper; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity; using Volo.Abp.Application;
using Microsoft.Extensions.DependencyInjection; using Volo.Abp.AutoMapper;
using Volo.Abp.Caching;
namespace LINGYUN.Abp.OssManagement using Volo.Abp.Modularity;
{
[DependsOn( namespace LINGYUN.Abp.OssManagement
typeof(AbpAutoMapperModule), {
typeof(AbpOssManagementDomainModule), [DependsOn(
typeof(AbpOssManagementApplicationContractsModule))] typeof(AbpOssManagementDomainModule),
public class AbpOssManagementApplicationModule : AbpModule typeof(AbpOssManagementApplicationContractsModule),
{ typeof(AbpCachingModule),
public override void ConfigureServices(ServiceConfigurationContext context) typeof(AbpAutoMapperModule),
{ typeof(AbpDddApplicationModule))]
context.Services.AddAutoMapperObjectMapper<AbpOssManagementApplicationModule>(); public class AbpOssManagementApplicationModule : AbpModule
{
Configure<AbpAutoMapperOptions>(options => public override void ConfigureServices(ServiceConfigurationContext context)
{ {
options.AddProfile<OssManagementApplicationAutoMapperProfile>(validate: true); context.Services.AddAutoMapperObjectMapper<AbpOssManagementApplicationModule>();
});
} Configure<AbpAutoMapperOptions>(options =>
} {
} options.AddProfile<OssManagementApplicationAutoMapperProfile>(validate: true);
});
}
}
}

2
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/FileValidater.cs → aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/FileValidater.cs

@ -31,7 +31,7 @@ namespace LINGYUN.Abp.OssManagement
_stringLocalizer = stringLocalizer; _stringLocalizer = stringLocalizer;
} }
public virtual async Task ValidationAsync(UploadOssObjectInput input) public virtual async Task ValidationAsync(UploadFile input)
{ {
var validation = await GetByCacheItemAsync(); var validation = await GetByCacheItemAsync();
if (validation.SizeLimit * 1024 * 1024 < input.TotalSize) if (validation.SizeLimit * 1024 * 1024 < input.TotalSize)

28
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssManagementApplicationServiceBase.cs

@ -1,14 +1,14 @@
using LINGYUN.Abp.OssManagement.Localization; using LINGYUN.Abp.OssManagement.Localization;
using Volo.Abp.Application.Services; using Volo.Abp.Application.Services;
namespace LINGYUN.Abp.OssManagement namespace LINGYUN.Abp.OssManagement
{ {
public class OssManagementApplicationServiceBase : ApplicationService public abstract class OssManagementApplicationServiceBase : ApplicationService
{ {
protected OssManagementApplicationServiceBase() protected OssManagementApplicationServiceBase()
{ {
LocalizationResource = typeof(AbpOssManagementResource); LocalizationResource = typeof(AbpOssManagementResource);
ObjectMapperContext = typeof(AbpOssManagementApplicationModule); ObjectMapperContext = typeof(AbpOssManagementApplicationModule);
} }
} }
} }

217
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/OssObjectAppService.cs

@ -1,116 +1,101 @@
using LINGYUN.Abp.Features.LimitValidation; using LINGYUN.Abp.Features.LimitValidation;
using LINGYUN.Abp.OssManagement.Features; using LINGYUN.Abp.OssManagement.Features;
using LINGYUN.Abp.OssManagement.Permissions; using LINGYUN.Abp.OssManagement.Permissions;
using LINGYUN.Abp.OssManagement.Settings; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization; using System;
using System; using System.Collections.Generic;
using System.Collections.Generic; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations; using System.IO;
using System.IO; using System.Threading.Tasks;
using System.Linq; using Volo.Abp.Features;
using System.Threading.Tasks; using Volo.Abp.Validation;
using Volo.Abp.Features;
using Volo.Abp.IO; namespace LINGYUN.Abp.OssManagement
using Volo.Abp.Settings; {
using Volo.Abp.Validation; [Authorize(AbpOssManagementPermissions.OssObject.Default)]
public class OssObjectAppService : OssManagementApplicationServiceBase, IOssObjectAppService
namespace LINGYUN.Abp.OssManagement {
{ protected IFileValidater FileValidater { get; }
[Authorize(AbpOssManagementPermissions.OssObject.Default)] protected IOssContainerFactory OssContainerFactory { get; }
public class OssObjectAppService : OssManagementApplicationServiceBase, IOssObjectAppService
{ public OssObjectAppService(
protected IOssContainerFactory OssContainerFactory { get; } IFileValidater fileValidater,
IOssContainerFactory ossContainerFactory)
public OssObjectAppService( {
IOssContainerFactory ossContainerFactory) FileValidater = fileValidater;
{ OssContainerFactory = ossContainerFactory;
OssContainerFactory = ossContainerFactory; }
}
[Authorize(AbpOssManagementPermissions.OssObject.Create)]
[Authorize(AbpOssManagementPermissions.OssObject.Create)] [RequiresFeature(AbpOssManagementFeatureNames.OssObject.UploadFile)]
[RequiresFeature(AbpOssManagementFeatureNames.OssObject.UploadFile)] [RequiresLimitFeature(
[RequiresLimitFeature( AbpOssManagementFeatureNames.OssObject.UploadLimit,
AbpOssManagementFeatureNames.OssObject.UploadLimit, AbpOssManagementFeatureNames.OssObject.UploadInterval,
AbpOssManagementFeatureNames.OssObject.UploadInterval, LimitPolicy.Month)]
LimitPolicy.Month)] public virtual async Task<OssObjectDto> CreateAsync(CreateOssObjectInput input)
public virtual async Task<OssObjectDto> CreateAsync(CreateOssObjectInput input) {
{ if (!input.Content.IsNullOrEmpty())
if (!input.Content.IsNullOrEmpty()) {
{ await FileValidater.ValidationAsync(new UploadFile
// 检查文件大小 {
var fileSizeLimited = await SettingProvider TotalSize = input.Content.Length,
.GetAsync( FileName = input.Object
AbpOssManagementSettingNames.FileLimitLength, });
AbpOssManagementSettingNames.DefaultFileLimitLength); }
if (fileSizeLimited * 1024 * 1024 < input.Content.Length)
{ var oss = CreateOssContainer();
ThrowValidationException(L["UploadFileSizeBeyondLimit", fileSizeLimited], nameof(input.Content));
} var createOssObjectRequest = new CreateOssObjectRequest(
input.Bucket,
// 文件扩展名 input.Object,
var fileExtensionName = FileHelper.GetExtension(input.Object); input.Content,
var fileAllowExtension = await SettingProvider.GetOrNullAsync(AbpOssManagementSettingNames.AllowFileExtensions); input.Path,
// 检查文件扩展名 input.ExpirationTime)
if (!fileAllowExtension.Split(',') {
.Any(fe => fe.Equals(fileExtensionName, StringComparison.CurrentCultureIgnoreCase))) Overwrite = input.Overwrite
{ };
ThrowValidationException(L["NotAllowedFileExtensionName", fileExtensionName], "FileName"); var ossObject = await oss.CreateObjectAsync(createOssObjectRequest);
}
} return ObjectMapper.Map<OssObject, OssObjectDto>(ossObject);
}
var oss = CreateOssContainer();
[Authorize(AbpOssManagementPermissions.OssObject.Delete)]
var createOssObjectRequest = new CreateOssObjectRequest( public virtual async Task BulkDeleteAsync(BulkDeleteOssObjectInput input)
input.Bucket, {
input.Object, var oss = CreateOssContainer();
input.Content,
input.Path, await oss.BulkDeleteObjectsAsync(input.Bucket, input.Objects, input.Path);
input.ExpirationTime) }
{
Overwrite = input.Overwrite [Authorize(AbpOssManagementPermissions.OssObject.Delete)]
}; public virtual async Task DeleteAsync(GetOssObjectInput input)
var ossObject = await oss.CreateObjectAsync(createOssObjectRequest); {
var oss = CreateOssContainer();
return ObjectMapper.Map<OssObject, OssObjectDto>(ossObject);
} await oss.DeleteObjectAsync(input.Bucket, input.Object, input.Path);
}
[Authorize(AbpOssManagementPermissions.OssObject.Delete)]
public virtual async Task BulkDeleteAsync(BulkDeleteOssObjectInput input) public virtual async Task<OssObjectDto> GetAsync(GetOssObjectInput input)
{ {
var oss = CreateOssContainer(); var oss = CreateOssContainer();
await oss.BulkDeleteObjectsAsync(input.Bucket, input.Objects, input.Path); var ossObject = await oss.GetObjectAsync(input.Bucket, input.Object, input.Path);
}
return ObjectMapper.Map<OssObject, OssObjectDto>(ossObject);
[Authorize(AbpOssManagementPermissions.OssObject.Delete)] }
public virtual async Task DeleteAsync(GetOssObjectInput input)
{ protected virtual IOssContainer CreateOssContainer()
var oss = CreateOssContainer(); {
return OssContainerFactory.Create();
await oss.DeleteObjectAsync(input.Bucket, input.Object, input.Path); }
}
private static void ThrowValidationException(string message, string memberName)
public virtual async Task<OssObjectDto> GetAsync(GetOssObjectInput input) {
{ throw new AbpValidationException(message,
var oss = CreateOssContainer(); new List<ValidationResult>
{
var ossObject = await oss.GetObjectAsync(input.Bucket, input.Object, input.Path); new ValidationResult(message, new[] {memberName})
});
return ObjectMapper.Map<OssObject, OssObjectDto>(ossObject); }
} }
}
protected virtual IOssContainer CreateOssContainer()
{
return OssContainerFactory.Create();
}
private static void ThrowValidationException(string message, string memberName)
{
throw new AbpValidationException(message,
new List<ValidationResult>
{
new ValidationResult(message, new[] {memberName})
});
}
}
}

16
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN/Abp/OssManagement/PublicFileAppService.cs

@ -0,0 +1,16 @@
namespace LINGYUN.Abp.OssManagement
{
public class PublicFileAppService : FileAppServiceBase, IPublicFileAppService
{
public PublicFileAppService(
IFileValidater fileValidater,
IOssContainerFactory ossContainerFactory)
: base(fileValidater, ossContainerFactory)
{
}
protected override string GetCurrentBucket()
{
return "public";
}
}
}

5
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN.Abp.OssManagement.Domain.Shared.csproj

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" /> <Import Project="..\..\..\common.props" />
@ -18,7 +18,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.Validation" Version="4.4.0" /> <PackageReference Include="Volo.Abp.Features" Version="4.4.0" />
<PackageReference Include="Volo.Abp.Validation" Version="4.4.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

72
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/AbpOssManagementDomainSharedModule.cs

@ -1,36 +1,36 @@
using LINGYUN.Abp.OssManagement.Localization; using LINGYUN.Abp.OssManagement.Localization;
using Volo.Abp.Localization; using Volo.Abp.Features;
using Volo.Abp.Localization.ExceptionHandling; using Volo.Abp.Localization;
using Volo.Abp.Modularity; using Volo.Abp.Localization.ExceptionHandling;
using Volo.Abp.Validation; using Volo.Abp.Modularity;
using Volo.Abp.Validation.Localization; using Volo.Abp.Validation;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.OssManagement namespace LINGYUN.Abp.OssManagement
{ {
[DependsOn(typeof(AbpValidationModule))] [DependsOn(
public class AbpOssManagementDomainSharedModule : AbpModule typeof(AbpFeaturesModule),
{ typeof(AbpValidationModule))]
public override void ConfigureServices(ServiceConfigurationContext context) public class AbpOssManagementDomainSharedModule : AbpModule
{ {
Configure<AbpVirtualFileSystemOptions>(options => public override void ConfigureServices(ServiceConfigurationContext context)
{ {
options.FileSets.AddEmbedded<AbpOssManagementDomainSharedModule>(); Configure<AbpVirtualFileSystemOptions>(options =>
}); {
options.FileSets.AddEmbedded<AbpOssManagementDomainSharedModule>();
Configure<AbpLocalizationOptions>(options => });
{
options.Resources Configure<AbpLocalizationOptions>(options =>
.Add<AbpOssManagementResource>("en") {
.AddBaseTypes( options.Resources
typeof(AbpValidationResource) .Add<AbpOssManagementResource>("en")
).AddVirtualJson("/LINGYUN/Abp/OssManagement/Localization/Resources"); .AddVirtualJson("/LINGYUN/Abp/OssManagement/Localization/Resources");
}); });
Configure<AbpExceptionLocalizationOptions>(options => Configure<AbpExceptionLocalizationOptions>(options =>
{ {
options.MapCodeNamespace(OssManagementErrorCodes.Namespace, typeof(AbpOssManagementResource)); options.MapCodeNamespace(OssManagementErrorCodes.Namespace, typeof(AbpOssManagementResource));
}); });
} }
} }
} }

0
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/Features/AbpOssManagementFeatureDefinitionProvider.cs → aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Features/AbpOssManagementFeatureDefinitionProvider.cs

82
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application.Contracts/LINGYUN/Abp/OssManagement/Features/AbpOssManagementFeatureNames.cs → aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Features/AbpOssManagementFeatureNames.cs

@ -1,41 +1,41 @@
namespace LINGYUN.Abp.OssManagement.Features namespace LINGYUN.Abp.OssManagement.Features
{ {
public class AbpOssManagementFeatureNames public class AbpOssManagementFeatureNames
{ {
public const string GroupName = "AbpOssManagement"; public const string GroupName = "AbpOssManagement";
public class OssObject public class OssObject
{ {
public const string Default = GroupName + ".OssObject"; public const string Default = GroupName + ".OssObject";
/// <summary> /// <summary>
/// 下载文件功能 /// 下载文件功能
/// </summary> /// </summary>
public const string DownloadFile = Default + ".DownloadFile"; public const string DownloadFile = Default + ".DownloadFile";
/// <summary> /// <summary>
/// 下载文件功能限制次数 /// 下载文件功能限制次数
/// </summary> /// </summary>
public const string DownloadLimit = Default + ".DownloadLimit"; public const string DownloadLimit = Default + ".DownloadLimit";
/// <summary> /// <summary>
/// 下载文件功能限制次数周期 /// 下载文件功能限制次数周期
/// </summary> /// </summary>
public const string DownloadInterval = Default + ".DownloadInterval"; public const string DownloadInterval = Default + ".DownloadInterval";
/// <summary> /// <summary>
/// 上传文件功能 /// 上传文件功能
/// </summary> /// </summary>
public const string UploadFile = Default + ".UploadFile"; public const string UploadFile = Default + ".UploadFile";
/// <summary> /// <summary>
/// 上传文件功能限制次数 /// 上传文件功能限制次数
/// </summary> /// </summary>
public const string UploadLimit = Default + ".UploadLimit"; public const string UploadLimit = Default + ".UploadLimit";
/// <summary> /// <summary>
/// 上传文件功能限制次数周期 /// 上传文件功能限制次数周期
/// </summary> /// </summary>
public const string UploadInterval = Default + ".UploadInterval"; public const string UploadInterval = Default + ".UploadInterval";
/// <summary> /// <summary>
/// 最大上传文件 /// 最大上传文件
/// </summary> /// </summary>
public const string MaxUploadFileCount = Default + ".MaxUploadFileCount"; public const string MaxUploadFileCount = Default + ".MaxUploadFileCount";
} }
} }
} }

1
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Localization/Resources/en.json

@ -1,6 +1,7 @@
{ {
"culture": "en", "culture": "en",
"texts": { "texts": {
"Abp.OssManagement:010000": "System definition containers cannot be deleted!",
"Abp.OssManagement:010001": "Cannot delete a container that has more than one object!", "Abp.OssManagement:010001": "Cannot delete a container that has more than one object!",
"Abp.OssManagement:010402": "The container name already exists!", "Abp.OssManagement:010402": "The container name already exists!",
"Abp.OssManagement:010404": "The queried container could not be found!", "Abp.OssManagement:010404": "The queried container could not be found!",

1
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/Localization/Resources/zh-Hans.json

@ -1,6 +1,7 @@
{ {
"culture": "zh-Hans", "culture": "zh-Hans",
"texts": { "texts": {
"Abp.OssManagement:010000": "不能删除系统定义容器!",
"Abp.OssManagement:010001": "不能删除存在多个对象的容器!", "Abp.OssManagement:010001": "不能删除存在多个对象的容器!",
"Abp.OssManagement:010402": "容器名称已经存在!", "Abp.OssManagement:010402": "容器名称已经存在!",
"Abp.OssManagement:010404": "未能找到查询的容器!", "Abp.OssManagement:010404": "未能找到查询的容器!",

35
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain.Shared/LINGYUN/Abp/OssManagement/OssManagementErrorCodes.cs

@ -1,17 +1,18 @@
namespace LINGYUN.Abp.OssManagement namespace LINGYUN.Abp.OssManagement
{ {
public static class OssManagementErrorCodes public static class OssManagementErrorCodes
{ {
public const string Namespace = "Abp.OssManagement"; public const string Namespace = "Abp.OssManagement";
public const string ContainerDeleteWithNotEmpty = Namespace + ":010001"; public const string ContainerDeleteWithStatic = Namespace + ":010000";
public const string ContainerAlreadyExists = Namespace + ":010402"; public const string ContainerDeleteWithNotEmpty = Namespace + ":010001";
public const string ContainerNotFound = Namespace + ":010404"; public const string ContainerAlreadyExists = Namespace + ":010402";
public const string ContainerNotFound = Namespace + ":010404";
public const string ObjectDeleteWithNotEmpty = Namespace + ":020001";
public const string ObjectAlreadyExists = Namespace + ":020402"; public const string ObjectDeleteWithNotEmpty = Namespace + ":020001";
public const string ObjectNotFound = Namespace + ":020404"; public const string ObjectAlreadyExists = Namespace + ":020402";
public const string ObjectNotFound = Namespace + ":020404";
public const string OssNameHasTooLong = Namespace + ":000405";
} public const string OssNameHasTooLong = Namespace + ":000405";
} }
}

49
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Domain/LINGYUN/Abp/OssManagement/AbpOssManagementDomainModule.cs

@ -1,17 +1,32 @@
using LINGYUN.Abp.Features.LimitValidation; using LINGYUN.Abp.Features.LimitValidation;
using Volo.Abp.Domain; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity; using Microsoft.Extensions.Options;
using Volo.Abp.MultiTenancy; using Volo.Abp;
using Volo.Abp.Domain;
namespace LINGYUN.Abp.OssManagement using Volo.Abp.Modularity;
{ using Volo.Abp.MultiTenancy;
[DependsOn(
typeof(AbpDddDomainModule), namespace LINGYUN.Abp.OssManagement
typeof(AbpMultiTenancyModule), {
typeof(AbpFeaturesLimitValidationModule), [DependsOn(
typeof(AbpOssManagementDomainSharedModule) typeof(AbpOssManagementDomainSharedModule),
)] typeof(AbpDddDomainModule),
public class AbpOssManagementDomainModule : AbpModule typeof(AbpMultiTenancyModule),
{ typeof(AbpFeaturesLimitValidationModule)
} )]
} public class AbpOssManagementDomainModule : AbpModule
{
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
// TODO: 是否有必要自动创建容器
var ossOptions = context.ServiceProvider.GetRequiredService<IOptions<AbpOssManagementOptions>>().Value;
var ossFactory = context.ServiceProvider.GetRequiredService<IOssContainerFactory>();
var ossContainer = ossFactory.Create();
foreach (var bucket in ossOptions.StaticBuckets)
{
_ = ossContainer.CreateIfNotExistsAsync(bucket);
}
}
}
}

36
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.FileSystem/LINGYUN/Abp/OssManagement/FileSystem/AbpOssManagementFileSystemModule.cs

@ -1,17 +1,19 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.BlobStoring.FileSystem; using Microsoft.Extensions.Options;
using Volo.Abp.Modularity; using Volo.Abp;
using Volo.Abp.BlobStoring.FileSystem;
namespace LINGYUN.Abp.OssManagement.FileSystem using Volo.Abp.Modularity;
{
[DependsOn( namespace LINGYUN.Abp.OssManagement.FileSystem
typeof(AbpBlobStoringFileSystemModule), {
typeof(AbpOssManagementDomainModule))] [DependsOn(
public class AbpOssManagementFileSystemModule : AbpModule typeof(AbpBlobStoringFileSystemModule),
{ typeof(AbpOssManagementDomainModule))]
public override void ConfigureServices(ServiceConfigurationContext context) public class AbpOssManagementFileSystemModule : AbpModule
{ {
context.Services.AddTransient<IOssContainerFactory, FileSystemOssContainerFactory>(); public override void ConfigureServices(ServiceConfigurationContext context)
} {
} context.Services.AddTransient<IOssContainerFactory, FileSystemOssContainerFactory>();
} }
}
}

15
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.FileSystem/LINGYUN/Abp/OssManagement/FileSystem/FileSystemOssContainer.cs

@ -25,6 +25,7 @@ namespace LINGYUN.Abp.OssManagement.FileSystem
protected IBlobContainerConfigurationProvider ConfigurationProvider { get; } protected IBlobContainerConfigurationProvider ConfigurationProvider { get; }
protected IServiceProvider ServiceProvider { get; } protected IServiceProvider ServiceProvider { get; }
protected FileSystemOssOptions Options { get; } protected FileSystemOssOptions Options { get; }
protected AbpOssManagementOptions OssOptions { get; }
public FileSystemOssContainer( public FileSystemOssContainer(
ICurrentTenant currentTenant, ICurrentTenant currentTenant,
@ -32,7 +33,8 @@ namespace LINGYUN.Abp.OssManagement.FileSystem
IServiceProvider serviceProvider, IServiceProvider serviceProvider,
IBlobFilePathCalculator blobFilePathCalculator, IBlobFilePathCalculator blobFilePathCalculator,
IBlobContainerConfigurationProvider configurationProvider, IBlobContainerConfigurationProvider configurationProvider,
IOptions<FileSystemOssOptions> options) IOptions<FileSystemOssOptions> options,
IOptions<AbpOssManagementOptions> ossOptions)
{ {
CurrentTenant = currentTenant; CurrentTenant = currentTenant;
Environment = environment; Environment = environment;
@ -40,6 +42,7 @@ namespace LINGYUN.Abp.OssManagement.FileSystem
FilePathCalculator = blobFilePathCalculator; FilePathCalculator = blobFilePathCalculator;
ConfigurationProvider = configurationProvider; ConfigurationProvider = configurationProvider;
Options = options.Value; Options = options.Value;
OssOptions = ossOptions.Value;
} }
public virtual Task BulkDeleteObjectsAsync(BulkDeleteObjectRequest request) public virtual Task BulkDeleteObjectsAsync(BulkDeleteObjectRequest request)
@ -173,6 +176,8 @@ namespace LINGYUN.Abp.OssManagement.FileSystem
public virtual Task DeleteAsync(string name) public virtual Task DeleteAsync(string name)
{ {
CheckStaticBucket(name);
var filePath = CalculateFilePath(name); var filePath = CalculateFilePath(name);
if (!Directory.Exists(filePath)) if (!Directory.Exists(filePath))
{ {
@ -533,6 +538,14 @@ namespace LINGYUN.Abp.OssManagement.FileSystem
return blobPath; return blobPath;
} }
protected virtual void CheckStaticBucket(string bucket)
{
if (OssOptions.CheckStaticBucket(bucket))
{
throw new BusinessException(code: OssManagementErrorCodes.ContainerDeleteWithStatic);
}
}
private void ThrowOfPathHasTooLong(string path) private void ThrowOfPathHasTooLong(string path)
{ {
// Windows 133 260 // Windows 133 260

96
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.FileSystem/LINGYUN/Abp/OssManagement/FileSystem/FileSystemOssContainerFactory.cs

@ -1,46 +1,50 @@
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using System; using System;
using Volo.Abp.BlobStoring; using Volo.Abp.BlobStoring;
using Volo.Abp.BlobStoring.FileSystem; using Volo.Abp.BlobStoring.FileSystem;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.OssManagement.FileSystem namespace LINGYUN.Abp.OssManagement.FileSystem
{ {
public class FileSystemOssContainerFactory : IOssContainerFactory public class FileSystemOssContainerFactory : IOssContainerFactory
{ {
protected ICurrentTenant CurrentTenant { get; } protected ICurrentTenant CurrentTenant { get; }
protected IHostEnvironment Environment { get; } protected IHostEnvironment Environment { get; }
protected IServiceProvider ServiceProvider { get; } protected IServiceProvider ServiceProvider { get; }
protected IBlobFilePathCalculator FilePathCalculator { get; } protected IBlobFilePathCalculator FilePathCalculator { get; }
protected IBlobContainerConfigurationProvider ConfigurationProvider { get; } protected IBlobContainerConfigurationProvider ConfigurationProvider { get; }
protected IOptions<FileSystemOssOptions> Options { get; } protected IOptions<FileSystemOssOptions> Options { get; }
protected IOptions<AbpOssManagementOptions> OssOptions { get; }
public FileSystemOssContainerFactory(
ICurrentTenant currentTenant, public FileSystemOssContainerFactory(
IHostEnvironment environment, ICurrentTenant currentTenant,
IServiceProvider serviceProvider, IHostEnvironment environment,
IBlobFilePathCalculator blobFilePathCalculator, IServiceProvider serviceProvider,
IBlobContainerConfigurationProvider configurationProvider, IBlobFilePathCalculator blobFilePathCalculator,
IOptions<FileSystemOssOptions> options) IBlobContainerConfigurationProvider configurationProvider,
{ IOptions<FileSystemOssOptions> options,
Environment = environment; IOptions<AbpOssManagementOptions> ossOptions)
CurrentTenant = currentTenant; {
ServiceProvider = serviceProvider; Environment = environment;
FilePathCalculator = blobFilePathCalculator; CurrentTenant = currentTenant;
ConfigurationProvider = configurationProvider; ServiceProvider = serviceProvider;
Options = options; FilePathCalculator = blobFilePathCalculator;
} ConfigurationProvider = configurationProvider;
Options = options;
public IOssContainer Create() OssOptions = ossOptions;
{ }
return new FileSystemOssContainer(
CurrentTenant, public IOssContainer Create()
Environment, {
ServiceProvider, return new FileSystemOssContainer(
FilePathCalculator, CurrentTenant,
ConfigurationProvider, Environment,
Options); ServiceProvider,
} FilePathCalculator,
} ConfigurationProvider,
} Options,
OssOptions);
}
}
}

1
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN.Abp.OssManagement.HttpApi.csproj

@ -12,7 +12,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\common\LINGYUN.Abp.Settings\LINGYUN.Abp.Settings.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.OssManagement.Application.Contracts\LINGYUN.Abp.OssManagement.Application.Contracts.csproj" /> <ProjectReference Include="..\LINGYUN.Abp.OssManagement.Application.Contracts\LINGYUN.Abp.OssManagement.Application.Contracts.csproj" />
</ItemGroup> </ItemGroup>

68
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/AbpOssManagementHttpApiModule.cs

@ -1,21 +1,47 @@
using Microsoft.Extensions.DependencyInjection; using LINGYUN.Abp.OssManagement.Localization;
using Volo.Abp.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity; using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Authorization.Localization;
namespace LINGYUN.Abp.OssManagement using Volo.Abp.Localization;
{ using Volo.Abp.Modularity;
[DependsOn( using Volo.Abp.Validation.Localization;
typeof(AbpOssManagementApplicationContractsModule), using Volo.Abp.AspNetCore.Mvc.DataAnnotations;
typeof(AbpAspNetCoreMvcModule) using Volo.Abp.AspNetCore.Mvc.Localization;
)]
public class AbpOssManagementHttpApiModule : AbpModule namespace LINGYUN.Abp.OssManagement
{ {
public override void PreConfigureServices(ServiceConfigurationContext context) [DependsOn(
{ typeof(AbpOssManagementApplicationContractsModule),
PreConfigure<IMvcBuilder>(mvcBuilder => typeof(AbpAspNetCoreMvcModule)
{ )]
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpOssManagementHttpApiModule).Assembly); public class AbpOssManagementHttpApiModule : AbpModule
}); {
} public override void PreConfigureServices(ServiceConfigurationContext context)
} {
} PreConfigure<IMvcBuilder>(mvcBuilder =>
{
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpOssManagementHttpApiModule).Assembly);
});
PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options =>
{
options.AddAssemblyResource(
typeof(AbpOssManagementResource),
typeof(AbpOssManagementApplicationContractsModule).Assembly);
});
}
//public override void ConfigureServices(ServiceConfigurationContext context)
//{
// Configure<AbpLocalizationOptions>(options =>
// {
// options.Resources
// .Get<AbpOssManagementResource>()
// .AddBaseTypes(
// typeof(AbpAuthorizationResource),
// typeof(AbpValidationResource)
// );
// });
//}
}
}

9
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/IFileValidater.cs

@ -1,9 +0,0 @@
using System.Threading.Tasks;
namespace LINGYUN.Abp.OssManagement
{
public interface IFileValidater
{
Task ValidationAsync(UploadOssObjectInput input);
}
}

4
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/StaticFilesController.cs

@ -1,7 +1,6 @@
using LINGYUN.Abp.OssManagement.Localization; using LINGYUN.Abp.OssManagement.Localization;
using LINGYUN.Abp.OssManagement.Permissions; using LINGYUN.Abp.OssManagement.Permissions;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
@ -15,9 +14,10 @@ using Volo.Abp.Validation;
namespace LINGYUN.Abp.OssManagement namespace LINGYUN.Abp.OssManagement
{ {
[RemoteService(Name = OssManagementRemoteServiceConsts.RemoteServiceName)]
[Area("oss-management")] [Area("oss-management")]
[Route("api/files/static")] [Route("api/files/static")]
[RemoteService(false)]
[ApiExplorerSettings(IgnoreApi = true)]
public class StaticFilesController : AbpController public class StaticFilesController : AbpController
{ {
private readonly IOssObjectAppService _ossObjectAppService; private readonly IOssObjectAppService _ossObjectAppService;

12
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.HttpApi/LINGYUN/Abp/OssManagement/UploadOssObjectInput.cs

@ -3,18 +3,13 @@ using System.ComponentModel.DataAnnotations;
namespace LINGYUN.Abp.OssManagement namespace LINGYUN.Abp.OssManagement
{ {
public class UploadOssObjectInput public class UploadOssObjectInput : UploadFile
{ {
public string Bucket { get; set; } public string Bucket { get; set; }
public string Path { get; set; } public string Path { get; set; }
#region 配合Uplaoder 分块传输 #region 配合Uplaoder 分块传输
/// <summary> /// <summary>
/// 文件名
/// </summary>
[Required]
public string FileName { get; set; }
/// <summary>
/// 常规块大小 /// 常规块大小
/// </summary> /// </summary>
[Required] [Required]
@ -34,11 +29,6 @@ namespace LINGYUN.Abp.OssManagement
/// </summary> /// </summary>
[Required] [Required]
public int TotalChunks { get; set; } public int TotalChunks { get; set; }
/// <summary>
/// 总文件大小
/// </summary>
[Required]
public long TotalSize { get; set; }
#endregion #endregion

20
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.SettingManagement/AbpOssManagementSettingManagementModule.cs

@ -1,20 +0,0 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.OssManagement.SettingManagement
{
[DependsOn(
typeof(AbpOssManagementApplicationContractsModule),
typeof(AbpAspNetCoreMvcModule))]
public class AbpOssManagementSettingManagementModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<IMvcBuilder>(mvcBuilder =>
{
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpOssManagementSettingManagementModule).Assembly);
});
}
}
}

101
aspnet-core/modules/oss-management/README.md

@ -1,50 +1,51 @@
# Oss-Management # Oss-Management
File-Management更名为Oss-Management File-Management更名为Oss-Management
## 模块说明 ## 模块说明
### 基础模块 ### 基础模块
* [LINGYUN.Abp.OssManagement.Domain.Shared](./LINGYUN.Abp.OssManagement.Domain.Shared) 领域层公共模块,定义了错误代码、本地化、模块设置 * [LINGYUN.Abp.OssManagement.Domain.Shared](./LINGYUN.Abp.OssManagement.Domain.Shared) 领域层公共模块,定义了错误代码、本地化、模块设置
* [LINGYUN.Abp.OssManagement.Domain](./LINGYUN.Abp.OssManagement.Domain) 领域层模块,定义了抽象的Oss容器与对象管理接口 * [LINGYUN.Abp.OssManagement.Domain](./LINGYUN.Abp.OssManagement.Domain) 领域层模块,定义了抽象的Oss容器与对象管理接口
* [LINGYUN.Abp.OssManagement.Application.Contracts](./LINGYUN.Abp.OssManagement.Application.Contracts) 应用服务层公共模块,定义了管理Oss的外部接口、权限、功能限制策略 * [LINGYUN.Abp.OssManagement.Application.Contracts](./LINGYUN.Abp.OssManagement.Application.Contracts) 应用服务层公共模块,定义了管理Oss的外部接口、权限、功能限制策略
* [LINGYUN.Abp.OssManagement.Application](./LINGYUN.Abp.OssManagement.Application) 应用服务层实现,实现了Oss管理接口 * [LINGYUN.Abp.OssManagement.Application](./LINGYUN.Abp.OssManagement.Application) 应用服务层实现,实现了Oss管理接口
* [LINGYUN.Abp.OssManagement.HttpApi](./LINGYUN.Abp.OssManagement.HttpApi) RestApi实现,实现了独立的对外RestApi接口 * [LINGYUN.Abp.OssManagement.HttpApi](./LINGYUN.Abp.OssManagement.HttpApi) RestApi实现,实现了独立的对外RestApi接口
* [LINGYUN.Abp.OssManagement.SettingManagement](./LINGYUN.Abp.OssManagement.SettingManagement) 设置管理模块,对外暴露自身的设置管理,用于网关聚合 * [LINGYUN.Abp.OssManagement.SettingManagement](./LINGYUN.Abp.OssManagement.SettingManagement) 设置管理模块,对外暴露自身的设置管理,用于网关聚合
### 高阶模块 ### 高阶模块
* [LINGYUN.Abp.OssManagement.Aliyun](./LINGYUN.Abp.OssManagement.Aliyun) Oss管理的阿里云实现,实现了部分阿里云Oss服务的容器与对象管理 * [LINGYUN.Abp.OssManagement.Aliyun](./LINGYUN.Abp.OssManagement.Aliyun) Oss管理的阿里云实现,实现了部分阿里云Oss服务的容器与对象管理
* [LINGYUN.Abp.OssManagement.FileSystem](./LINGYUN.Abp.OssManagement.FileSystem) Oss管理的本地文件系统实现,实现了部分本地文件系统的容器(目录)与对象(文件/目录)管理 * [LINGYUN.Abp.OssManagement.FileSystem](./LINGYUN.Abp.OssManagement.FileSystem) Oss管理的本地文件系统实现,实现了部分本地文件系统的容器(目录)与对象(文件/目录)管理
* [LINGYUN.Abp.OssManagement.FileSystem.ImageSharp](./LINGYUN.Abp.OssManagement.FileSystem.ImageSharp) Oss本地对象的ImageSharp扩展,当前端传递需求处理对象时,此模块用于实现基于图形文件流的处理 * [LINGYUN.Abp.OssManagement.FileSystem.ImageSharp](./LINGYUN.Abp.OssManagement.FileSystem.ImageSharp) Oss本地对象的ImageSharp扩展,当前端传递需求处理对象时,此模块用于实现基于图形文件流的处理
### 权限定义 ### 权限定义
* AbpOssManagement.Container 授权对象是否允许访问容器(bucket) * AbpOssManagement.Container 授权对象是否允许访问容器(bucket)
* AbpOssManagement.Container.Create 授权对象是否允许创建容器(bucket) * AbpOssManagement.Container.Create 授权对象是否允许创建容器(bucket)
* AbpOssManagement.Container.Delete 授权对象是否允许删除容器(bucket) * AbpOssManagement.Container.Delete 授权对象是否允许删除容器(bucket)
* AbpOssManagement.OssObject 授权对象是否允许访问Oss对象 * AbpOssManagement.OssObject 授权对象是否允许访问Oss对象
* AbpOssManagement.OssObject.Create 授权对象是否允许创建Oss对象 * AbpOssManagement.OssObject.Create 授权对象是否允许创建Oss对象
* AbpOssManagement.OssObject.Delete 授权对象是否允许删除Oss对象 * AbpOssManagement.OssObject.Delete 授权对象是否允许删除Oss对象
* AbpOssManagement.OssObject.Download 授权对象是否允许下载Oss对象 * AbpOssManagement.OssObject.Download 授权对象是否允许下载Oss对象
### 功能定义 ### 功能定义
* AbpOssManagement.OssObject.DownloadFile 用户可以下载文件 * AbpOssManagement.OssObject.DownloadFile 用户可以下载文件
* AbpOssManagement.OssObject.DownloadLimit 用户在周期内允许下载文件的最大次数,范围0-1000000 * AbpOssManagement.OssObject.DownloadLimit 用户在周期内允许下载文件的最大次数,范围0-1000000
* AbpOssManagement.OssObject.DownloadInterval 用户限制下载文件次数的周期,时钟刻度:月,默认: 1,范围1-12 * AbpOssManagement.OssObject.DownloadInterval 用户限制下载文件次数的周期,时钟刻度:月,默认: 1,范围1-12
* AbpOssManagement.OssObject.UploadFile 用户可以上传文件 * AbpOssManagement.OssObject.UploadFile 用户可以上传文件
* AbpOssManagement.OssObject.UploadLimit 用户在周期内允许上传文件的最大次数,范围0-1000000 * AbpOssManagement.OssObject.UploadLimit 用户在周期内允许上传文件的最大次数,范围0-1000000
* AbpOssManagement.OssObject.UploadInterval 用户限制上传文件次数的周期,时钟刻度:月,默认: 1,范围1-12 * AbpOssManagement.OssObject.UploadInterval 用户限制上传文件次数的周期,时钟刻度:月,默认: 1,范围1-12
* AbpOssManagement.OssObject.MaxUploadFileCount 单次上传文件的数量,未实现 * AbpOssManagement.OssObject.MaxUploadFileCount 单次上传文件的数量,未实现
### 配置定义 ### 配置定义
* Abp.OssManagement.DownloadPackageSize 下载分包大小,分块下载时单次传输的数据大小,未实现 * Abp.OssManagement.DownloadPackageSize 下载分包大小,分块下载时单次传输的数据大小,未实现
* Abp.OssManagement.FileLimitLength 上传文件限制大小,默认:100 * Abp.OssManagement.FileLimitLength 上传文件限制大小,默认:100
* Abp.OssManagement.AllowFileExtensions 允许的上传文件扩展名,多个扩展名以逗号分隔,默认:dll,zip,rar,txt,log,xml,config,json,jpeg,jpg,png,bmp,ico,xlsx,xltx,xls,xlt,docs,dots,doc,dot,pptx,potx,ppt,pot,chm * Abp.OssManagement.AllowFileExtensions 允许的上传文件扩展名,多个扩展名以逗号分隔,默认:dll,zip,rar,txt,log,xml,config,json,jpeg,jpg,png,bmp,ico,xlsx,xltx,xls,xlt,docs,dots,doc,dot,pptx,potx,ppt,pot,chm
## 更新日志 ## 更新日志
*【2021-03-10】 变更FileManagement命名空间为OssManagement *【2021-03-10】 变更FileManagement命名空间为OssManagement
*【2021-10-22】 增加PublicFilesController用于身份认证通过的用户上传/下载文件,所有操作限定在用户目录下

42
aspnet-core/services/localization/LINGYUN.Abp.LocalizationManagement.HttpApi.Host/Properties/launchSettings.json

@ -1,21 +1,21 @@
{ {
"iisSettings": { "iisSettings": {
"windowsAuthentication": false, "windowsAuthentication": false,
"anonymousAuthentication": true, "anonymousAuthentication": true,
"iisExpress": { "iisExpress": {
"applicationUrl": "http://localhost:30030", "applicationUrl": "http://localhost:30030",
"sslPort": 0 "sslPort": 0
} }
}, },
"profiles": { "profiles": {
"LINGYUN.Abp.LocalizationManagement.HttpApi.Host": { "LINGYUN.Abp.LocalizationManagement.HttpApi.Host": {
"commandName": "Project", "commandName": "Project",
"dotnetRunMessages": "true", "dotnetRunMessages": "true",
"launchBrowser": false, "launchBrowser": false,
"applicationUrl": "http://0.0.0.0:30030", "applicationUrl": "http://0.0.0.0:30030",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }
} }
} }
} }

675
aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/AppPlatformHttpApiHostModule.cs

@ -1,333 +1,342 @@
using DotNetCore.CAP; using DotNetCore.CAP;
using LINGYUN.Abp.AspNetCore.HttpOverrides; using LINGYUN.Abp.AspNetCore.HttpOverrides;
using LINGYUN.Abp.EventBus.CAP; using LINGYUN.Abp.EventBus.CAP;
using LINGYUN.Abp.ExceptionHandling; using LINGYUN.Abp.ExceptionHandling;
using LINGYUN.Abp.ExceptionHandling.Emailing; using LINGYUN.Abp.ExceptionHandling.Emailing;
using LINGYUN.Abp.Features.LimitValidation.Redis; using LINGYUN.Abp.Features.LimitValidation.Redis;
using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore; using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore;
using LINGYUN.Abp.MultiTenancy.DbFinder; using LINGYUN.Abp.MultiTenancy.DbFinder;
using LINGYUN.Abp.Notifications; using LINGYUN.Abp.Notifications;
using LINGYUN.Abp.OssManagement; using LINGYUN.Abp.OssManagement;
using LINGYUN.Abp.OssManagement.FileSystem; using LINGYUN.Abp.OssManagement.FileSystem;
using LINGYUN.Abp.OssManagement.FileSystem.ImageSharp; using LINGYUN.Abp.OssManagement.FileSystem.ImageSharp;
using LINGYUN.Abp.OssManagement.SettingManagement; using LINGYUN.Abp.OssManagement.SettingManagement;
using LINGYUN.Platform.EntityFrameworkCore; using LINGYUN.Platform.EntityFrameworkCore;
using LINGYUN.Platform.HttpApi; using LINGYUN.Platform.HttpApi;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.Caching.StackExchangeRedis; using Microsoft.Extensions.Caching.StackExchangeRedis;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
using StackExchange.Redis; using StackExchange.Redis;
using System; using System;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
using System.Text.Unicode; using System.Text.Unicode;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.AspNetCore.Authentication.JwtBearer; using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.MultiTenancy; using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.AspNetCore.Security.Claims; using Volo.Abp.AspNetCore.Security.Claims;
using Volo.Abp.Auditing; using Volo.Abp.Auditing;
using Volo.Abp.AuditLogging.EntityFrameworkCore; using Volo.Abp.AuditLogging.EntityFrameworkCore;
using Volo.Abp.Autofac; using Volo.Abp.Autofac;
using Volo.Abp.BlobStoring; using Volo.Abp.BlobStoring;
using Volo.Abp.BlobStoring.FileSystem; using Volo.Abp.BlobStoring.FileSystem;
using Volo.Abp.Caching; using Volo.Abp.Caching;
using Volo.Abp.Caching.StackExchangeRedis; using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.Data; using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.FeatureManagement.EntityFrameworkCore; using Volo.Abp.FeatureManagement.EntityFrameworkCore;
using Volo.Abp.Http.Client.IdentityModel.Web; using Volo.Abp.Http.Client.IdentityModel.Web;
using Volo.Abp.Identity; using Volo.Abp.Identity;
using Volo.Abp.Json; using Volo.Abp.Json;
using Volo.Abp.Json.SystemTextJson; using Volo.Abp.Json.SystemTextJson;
using Volo.Abp.Localization; using Volo.Abp.Localization;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using Volo.Abp.PermissionManagement.EntityFrameworkCore; using Volo.Abp.PermissionManagement.EntityFrameworkCore;
using Volo.Abp.Security.Claims; using Volo.Abp.Security.Claims;
using Volo.Abp.Security.Encryption; using Volo.Abp.Security.Encryption;
using Volo.Abp.SettingManagement.EntityFrameworkCore; using Volo.Abp.SettingManagement.EntityFrameworkCore;
using Volo.Abp.TenantManagement.EntityFrameworkCore; using Volo.Abp.TenantManagement.EntityFrameworkCore;
using Volo.Abp.Threading; using Volo.Abp.Threading;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Platform namespace LINGYUN.Platform
{ {
[DependsOn( [DependsOn(
// typeof(AbpOssManagementAliyunModule), // typeof(AbpOssManagementAliyunModule),
typeof(AbpOssManagementFileSystemModule), // 本地文件系统提供者模块 typeof(AbpOssManagementFileSystemModule), // 本地文件系统提供者模块
typeof(AbpOssManagementFileSystemImageSharpModule), // 本地文件系统图形处理模块 typeof(AbpOssManagementFileSystemImageSharpModule), // 本地文件系统图形处理模块
typeof(AbpOssManagementApplicationModule), typeof(AbpOssManagementApplicationModule),
typeof(AbpOssManagementHttpApiModule), typeof(AbpOssManagementHttpApiModule),
typeof(AbpOssManagementSettingManagementModule), typeof(AbpOssManagementSettingManagementModule),
typeof(PlatformApplicationModule), typeof(PlatformApplicationModule),
typeof(PlatformHttpApiModule), typeof(PlatformHttpApiModule),
typeof(PlatformEntityFrameworkCoreModule), typeof(PlatformEntityFrameworkCoreModule),
typeof(AbpIdentityHttpApiClientModule), typeof(AbpIdentityHttpApiClientModule),
typeof(AbpHttpClientIdentityModelWebModule), typeof(AbpHttpClientIdentityModelWebModule),
typeof(AbpAspNetCoreMultiTenancyModule), typeof(AbpAspNetCoreMultiTenancyModule),
typeof(AbpFeatureManagementEntityFrameworkCoreModule), typeof(AbpFeatureManagementEntityFrameworkCoreModule),
typeof(AbpAuditLoggingEntityFrameworkCoreModule), typeof(AbpAuditLoggingEntityFrameworkCoreModule),
typeof(AbpTenantManagementEntityFrameworkCoreModule), typeof(AbpTenantManagementEntityFrameworkCoreModule),
typeof(AbpSettingManagementEntityFrameworkCoreModule), typeof(AbpSettingManagementEntityFrameworkCoreModule),
typeof(AbpPermissionManagementEntityFrameworkCoreModule), typeof(AbpPermissionManagementEntityFrameworkCoreModule),
typeof(AbpLocalizationManagementEntityFrameworkCoreModule), typeof(AbpLocalizationManagementEntityFrameworkCoreModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule), typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(AbpNotificationModule), typeof(AbpNotificationModule),
typeof(AbpEmailingExceptionHandlingModule), typeof(AbpEmailingExceptionHandlingModule),
typeof(AbpCAPEventBusModule), typeof(AbpCAPEventBusModule),
typeof(AbpFeaturesValidationRedisModule), typeof(AbpFeaturesValidationRedisModule),
// typeof(AbpFeaturesClientModule),// 当需要客户端特性限制时取消注释此模块 // typeof(AbpFeaturesClientModule),// 当需要客户端特性限制时取消注释此模块
// typeof(AbpFeaturesValidationRedisClientModule),// 当需要客户端特性限制时取消注释此模块 // typeof(AbpFeaturesValidationRedisClientModule),// 当需要客户端特性限制时取消注释此模块
typeof(AbpDbFinderMultiTenancyModule), typeof(AbpDbFinderMultiTenancyModule),
typeof(AbpCachingStackExchangeRedisModule), typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpAspNetCoreHttpOverridesModule), typeof(AbpAspNetCoreHttpOverridesModule),
typeof(AbpAutofacModule) typeof(AbpAutofacModule)
)] )]
public class AppPlatformHttpApiHostModule : AbpModule public class AppPlatformHttpApiHostModule : AbpModule
{ {
public override void PreConfigureServices(ServiceConfigurationContext context) public override void PreConfigureServices(ServiceConfigurationContext context)
{ {
var configuration = context.Services.GetConfiguration(); var configuration = context.Services.GetConfiguration();
PreConfigure<CapOptions>(options => PreConfigure<CapOptions>(options =>
{ {
options options
.UseMySql(configuration.GetConnectionString("Default")) .UseMySql(configuration.GetConnectionString("Default"))
.UseRabbitMQ(rabbitMQOptions => .UseRabbitMQ(rabbitMQOptions =>
{ {
configuration.GetSection("CAP:RabbitMQ").Bind(rabbitMQOptions); configuration.GetSection("CAP:RabbitMQ").Bind(rabbitMQOptions);
}) })
.UseDashboard(); .UseDashboard();
}); });
} }
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
var hostingEnvironment = context.Services.GetHostingEnvironment(); var hostingEnvironment = context.Services.GetHostingEnvironment();
var configuration = hostingEnvironment.BuildConfiguration(); var configuration = hostingEnvironment.BuildConfiguration();
// 配置Ef // 配置Ef
Configure<AbpDbContextOptions>(options => Configure<AbpDbContextOptions>(options =>
{ {
options.UseMySQL(); options.UseMySQL();
}); });
//// 中文序列化的编码问题 //// 中文序列化的编码问题
Configure<AbpSystemTextJsonSerializerOptions>(options => Configure<AbpSystemTextJsonSerializerOptions>(options =>
{ {
options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
}); });
Configure<KestrelServerOptions>(options => Configure<KestrelServerOptions>(options =>
{ {
options.Limits.MaxRequestBodySize = null; options.Limits.MaxRequestBodySize = null;
options.Limits.MaxRequestBufferSize = null; options.Limits.MaxRequestBufferSize = null;
}); });
Configure<AbpBlobStoringOptions>(options => Configure<AbpBlobStoringOptions>(options =>
{ {
options.Containers.ConfigureAll((containerName, containerConfiguration) => options.Containers.ConfigureAll((containerName, containerConfiguration) =>
{ {
containerConfiguration.UseFileSystem(fileSystem => containerConfiguration.UseFileSystem(fileSystem =>
{ {
fileSystem.BasePath = Path.Combine(Directory.GetCurrentDirectory(), "file-blob-storing"); fileSystem.BasePath = Path.Combine(Directory.GetCurrentDirectory(), "file-blob-storing");
}); });
}); });
}); });
// 加解密 // 加解密
Configure<AbpStringEncryptionOptions>(options => Configure<AbpStringEncryptionOptions>(options =>
{ {
var encryptionConfiguration = configuration.GetSection("Encryption"); var encryptionConfiguration = configuration.GetSection("Encryption");
if (encryptionConfiguration.Exists()) if (encryptionConfiguration.Exists())
{ {
options.DefaultPassPhrase = encryptionConfiguration["PassPhrase"] ?? options.DefaultPassPhrase; options.DefaultPassPhrase = encryptionConfiguration["PassPhrase"] ?? options.DefaultPassPhrase;
options.DefaultSalt = encryptionConfiguration.GetSection("Salt").Exists() options.DefaultSalt = encryptionConfiguration.GetSection("Salt").Exists()
? Encoding.ASCII.GetBytes(encryptionConfiguration["Salt"]) ? Encoding.ASCII.GetBytes(encryptionConfiguration["Salt"])
: options.DefaultSalt; : options.DefaultSalt;
options.InitVectorBytes = encryptionConfiguration.GetSection("InitVector").Exists() options.InitVectorBytes = encryptionConfiguration.GetSection("InitVector").Exists()
? Encoding.ASCII.GetBytes(encryptionConfiguration["InitVector"]) ? Encoding.ASCII.GetBytes(encryptionConfiguration["InitVector"])
: options.InitVectorBytes; : options.InitVectorBytes;
} }
}); });
// 自定义需要处理的异常 // 自定义需要处理的异常
Configure<AbpExceptionHandlingOptions>(options => Configure<AbpExceptionHandlingOptions>(options =>
{ {
// 加入需要处理的异常类型 // 加入需要处理的异常类型
options.Handlers.Add<Volo.Abp.Data.AbpDbConcurrencyException>(); options.Handlers.Add<Volo.Abp.Data.AbpDbConcurrencyException>();
options.Handlers.Add<AbpInitializationException>(); options.Handlers.Add<AbpInitializationException>();
options.Handlers.Add<ObjectDisposedException>(); options.Handlers.Add<ObjectDisposedException>();
options.Handlers.Add<StackOverflowException>(); options.Handlers.Add<StackOverflowException>();
options.Handlers.Add<OutOfMemoryException>(); options.Handlers.Add<OutOfMemoryException>();
options.Handlers.Add<System.Data.Common.DbException>(); options.Handlers.Add<System.Data.Common.DbException>();
options.Handlers.Add<Microsoft.EntityFrameworkCore.DbUpdateException>(); options.Handlers.Add<Microsoft.EntityFrameworkCore.DbUpdateException>();
options.Handlers.Add<System.Data.DBConcurrencyException>(); options.Handlers.Add<System.Data.DBConcurrencyException>();
}); });
// 自定义需要发送邮件通知的异常类型
Configure<AbpEmailExceptionHandlingOptions>(options => Configure<Volo.Abp.AspNetCore.ExceptionHandling.AbpExceptionHandlingOptions>(options =>
{ {
// 是否发送堆栈信息 // 是否发送错误详情
options.SendStackTrace = true; options.SendExceptionsDetailsToClients = false;
// 未指定异常接收者的默认接收邮件 });
// 指定自己的邮件地址
// options.DefaultReceiveEmail = "colin.in@foxmail.com"; // 自定义需要发送邮件通知的异常类型
}); Configure<AbpEmailExceptionHandlingOptions>(options =>
{
Configure<AbpDistributedCacheOptions>(options => // 是否发送堆栈信息
{ options.SendStackTrace = true;
// 最好统一命名,不然某个缓存变动其他应用服务有例外发生 // 未指定异常接收者的默认接收邮件
options.KeyPrefix = "LINGYUN.Abp.Application"; // 指定自己的邮件地址
// 滑动过期30天 // options.DefaultReceiveEmail = "colin.in@foxmail.com";
options.GlobalCacheEntryOptions.SlidingExpiration = TimeSpan.FromDays(30); });
// 绝对过期60天
options.GlobalCacheEntryOptions.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(60); Configure<AbpDistributedCacheOptions>(options =>
}); {
// 最好统一命名,不然某个缓存变动其他应用服务有例外发生
Configure<RedisCacheOptions>(options => options.KeyPrefix = "LINGYUN.Abp.Application";
{ // 滑动过期30天
var redisConfig = ConfigurationOptions.Parse(options.Configuration); options.GlobalCacheEntryOptions.SlidingExpiration = TimeSpan.FromDays(30);
options.ConfigurationOptions = redisConfig; // 绝对过期60天
options.InstanceName = configuration["Redis:InstanceName"]; options.GlobalCacheEntryOptions.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(60);
}); });
Configure<AbpVirtualFileSystemOptions>(options => Configure<RedisCacheOptions>(options =>
{ {
options.FileSets.AddEmbedded<AppPlatformHttpApiHostModule>("LINGYUN.Platform"); var redisConfig = ConfigurationOptions.Parse(options.Configuration);
}); options.ConfigurationOptions = redisConfig;
options.InstanceName = configuration["Redis:InstanceName"];
// 多租户 });
Configure<AbpMultiTenancyOptions>(options =>
{ Configure<AbpVirtualFileSystemOptions>(options =>
options.IsEnabled = true; {
}); options.FileSets.AddEmbedded<AppPlatformHttpApiHostModule>("LINGYUN.Platform");
});
Configure<AbpAuditingOptions>(options =>
{ // 多租户
options.ApplicationName = "Platform"; Configure<AbpMultiTenancyOptions>(options =>
// 是否启用实体变更记录 {
var entitiesChangedConfig = configuration.GetSection("App:TrackingEntitiesChanged"); options.IsEnabled = true;
if (entitiesChangedConfig.Exists() && entitiesChangedConfig.Get<bool>()) });
{
options Configure<AbpAuditingOptions>(options =>
.EntityHistorySelectors {
.AddAllEntities(); options.ApplicationName = "Platform";
} // 是否启用实体变更记录
}); var entitiesChangedConfig = configuration.GetSection("App:TrackingEntitiesChanged");
if (entitiesChangedConfig.Exists() && entitiesChangedConfig.Get<bool>())
// Swagger {
context.Services.AddSwaggerGen( options
options => .EntityHistorySelectors
{ .AddAllEntities();
options.SwaggerDoc("v1", new OpenApiInfo { Title = "Platform API", Version = "v1" }); }
options.DocInclusionPredicate((docName, description) => true); });
options.CustomSchemaIds(type => type.FullName);
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme // Swagger
{ context.Services.AddSwaggerGen(
Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"", options =>
Name = "Authorization", {
In = ParameterLocation.Header, options.SwaggerDoc("v1", new OpenApiInfo { Title = "Platform API", Version = "v1" });
Scheme = "bearer", options.DocInclusionPredicate((docName, description) => true);
Type = SecuritySchemeType.Http, options.CustomSchemaIds(type => type.FullName);
BearerFormat = "JWT" options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
}); {
options.AddSecurityRequirement(new OpenApiSecurityRequirement Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
{ Name = "Authorization",
{ In = ParameterLocation.Header,
new OpenApiSecurityScheme Scheme = "bearer",
{ Type = SecuritySchemeType.Http,
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } BearerFormat = "JWT"
}, });
new string[] { } options.AddSecurityRequirement(new OpenApiSecurityRequirement
} {
}); {
}); new OpenApiSecurityScheme
{
// 支持本地化语言类型 Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }
Configure<AbpLocalizationOptions>(options => },
{ new string[] { }
options.Languages.Add(new LanguageInfo("en", "en", "English")); }
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); });
});
options.Resources.AddDynamic();
}); // 支持本地化语言类型
Configure<AbpLocalizationOptions>(options =>
Configure<AbpClaimsMapOptions>(options => {
{ options.Languages.Add(new LanguageInfo("en", "en", "English"));
options.Maps.TryAdd("name", () => AbpClaimTypes.UserName); options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
});
options.Resources.AddDynamic();
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) });
.AddJwtBearer(options =>
{ Configure<AbpClaimsMapOptions>(options =>
options.Authority = configuration["AuthServer:Authority"]; {
options.RequireHttpsMetadata = false; options.Maps.TryAdd("name", () => AbpClaimTypes.UserName);
options.Audience = configuration["AuthServer:ApiName"]; });
});
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
if (!hostingEnvironment.IsDevelopment()) .AddJwtBearer(options =>
{ {
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); options.Authority = configuration["AuthServer:Authority"];
context.Services options.RequireHttpsMetadata = false;
.AddDataProtection() options.Audience = configuration["AuthServer:ApiName"];
.PersistKeysToStackExchangeRedis(redis, "Platform-Protection-Keys"); });
}
} if (!hostingEnvironment.IsDevelopment())
{
//public override void OnPostApplicationInitialization(ApplicationInitializationContext context) var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
//{ context.Services
// var backgroundJobManager = context.ServiceProvider.GetRequiredService<IBackgroundJobManager>(); .AddDataProtection()
// // 五分钟执行一次的定时任务 .PersistKeysToStackExchangeRedis(redis, "Platform-Protection-Keys");
// AsyncHelper.RunSync(async () => await }
// backgroundJobManager.EnqueueAsync(CronGenerator.Minute(5), new NotificationCleanupExpritionJobArgs(200))); }
//}
//public override void OnPostApplicationInitialization(ApplicationInitializationContext context)
public override void OnApplicationInitialization(ApplicationInitializationContext context) //{
{ // var backgroundJobManager = context.ServiceProvider.GetRequiredService<IBackgroundJobManager>();
var app = context.GetApplicationBuilder(); // // 五分钟执行一次的定时任务
var env = context.GetEnvironment(); // AsyncHelper.RunSync(async () => await
// http调用链 // backgroundJobManager.EnqueueAsync(CronGenerator.Minute(5), new NotificationCleanupExpritionJobArgs(200)));
app.UseCorrelationId(); //}
// 虚拟文件系统
app.UseStaticFiles(); public override void OnApplicationInitialization(ApplicationInitializationContext context)
// 本地化 {
app.UseAbpRequestLocalization(); var app = context.GetApplicationBuilder();
// 多租户 var env = context.GetEnvironment();
app.UseMultiTenancy(); // http调用链
//路由 app.UseCorrelationId();
app.UseRouting(); // 虚拟文件系统
// 认证 app.UseStaticFiles();
app.UseAuthentication(); // 本地化
// jwt app.UseAbpRequestLocalization();
app.UseJwtTokenMiddleware(); // 多租户
// 授权 app.UseMultiTenancy();
app.UseAuthorization(); //路由
// Swagger app.UseRouting();
app.UseSwagger(); // 认证
// Swagger可视化界面 app.UseAuthentication();
app.UseSwaggerUI(options => // jwt
{ app.UseJwtTokenMiddleware();
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support Platform API"); // 授权
}); app.UseAuthorization();
// 审计日志 // Swagger
app.UseAuditing(); app.UseSwagger();
// 路由 // Swagger可视化界面
app.UseConfiguredEndpoints(); app.UseSwaggerUI(options =>
{
if (env.IsDevelopment()) options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support Platform API");
{ });
AsyncHelper.RunSync(async () => // 审计日志
await app.ApplicationServices.GetRequiredService<IDataSeeder>() app.UseAuditing();
.SeedAsync()); // 工作单元
} app.UseUnitOfWork();
} // 路由
} app.UseConfiguredEndpoints();
}
if (env.IsDevelopment())
{
AsyncHelper.RunSync(async () =>
await app.ApplicationServices.GetRequiredService<IDataSeeder>()
.SeedAsync());
}
}
}
}

Loading…
Cancel
Save