Browse Source

Merge pull request #1368 from colinin/oss-configuration

feat(oss-management): Use a configured object storage provider
pull/1377/head
yx lin 3 months ago
committed by GitHub
parent
commit
27aac6dc7e
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 11
      aspnet-core/framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN/Abp/BlobStoring/Tencent/CosClientFactory.cs
  2. 2
      aspnet-core/framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN/Abp/BlobStoring/Tencent/ICosClientFactory.cs
  3. 2
      aspnet-core/framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN/Abp/BlobStoring/Tencent/TencentBlobProviderConfiguration.cs
  4. 38
      aspnet-core/framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN/Abp/BlobStoring/Tencent/TencentCloudBlobProvider.cs
  5. 4
      aspnet-core/framework/cloud-tencent/LINGYUN.Abp.Tencent/LINGYUN/Abp/Tencent/AbpTencentCloudModule.cs
  6. 26
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Aliyun/LINGYUN/Abp/OssManagement/Aliyun/AbpOssManagementAliyunModule.cs
  7. 32
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.FileSystem/LINGYUN/Abp/OssManagement/FileSystem/AbpOssManagementFileSystemModule.cs
  8. 26
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Minio/LINGYUN/Abp/OssManagement/Minio/AbpOssManagementMinioModule.cs
  9. 3
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Minio/LINGYUN/Abp/OssManagement/Minio/MinioOssContainer.cs
  10. 27
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Nexus/LINGYUN/Abp/OssManagement/Nexus/AbpOssManagementNexusModule.cs
  11. 21
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Nexus/Microsoft/Extensions/DependencyInjection/NexusOssContainerServiceCollectionExtensions.cs
  12. 26
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Tencent/LINGYUN/Abp/OssManagement/Tencent/AbpOssManagementTencentModule.cs
  13. 60
      aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Tencent/LINGYUN/Abp/OssManagement/Tencent/TencentOssContainer.cs
  14. 7
      aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/appsettings.Development.json

11
aspnet-core/framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN/Abp/BlobStoring/Tencent/CosClientFactory.cs

@ -33,6 +33,13 @@ public class CosClientFactory : AbstractTencentCloudClientFactory<CosXml, Tencen
return await CreateAsync(configuration.GetTencentConfiguration());
}
public virtual Task<TencentBlobProviderConfiguration> GetConfigurationAsync<TContainer>()
{
var configuration = ConfigurationProvider.Get<TContainer>();
return Task.FromResult(configuration.GetTencentConfiguration());
}
protected override CosXml CreateClient(TencentBlobProviderConfiguration configuration, TencentCloudClientCacheItem cloudCache)
{
// 推荐全局单个对象,需要解决缓存过期事件
@ -46,8 +53,10 @@ public class CosClientFactory : AbstractTencentCloudClientFactory<CosXml, Tencen
{
var configBuilder = new CosXmlConfig.Builder();
configBuilder
.IsHttps(true)
.SetAppid(configuration.AppId)
.SetRegion(configuration.Region);
.SetRegion(configuration.Region)
.SetDebugLog(true);
var cred = new DefaultQCloudCredentialProvider(
cloudCache.SecretId,

2
aspnet-core/framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN/Abp/BlobStoring/Tencent/ICosClientFactory.cs

@ -8,4 +8,6 @@ public interface ICosClientFactory
Task<CosXml> CreateAsync<TContainer>();
Task<CosXml> CreateAsync(TencentBlobProviderConfiguration configuration);
Task<TencentBlobProviderConfiguration> GetConfigurationAsync<TContainer>();
}

2
aspnet-core/framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN/Abp/BlobStoring/Tencent/TencentBlobProviderConfiguration.cs

@ -40,7 +40,7 @@ public class TencentBlobProviderConfiguration
/// 创建命名空间时防盗链列表
/// </summary>
public List<string> CreateBucketReferer {
get => _containerConfiguration.GetConfiguration<List<string>>(TencentBlobProviderConfigurationNames.CreateBucketReferer);
get => _containerConfiguration.GetConfigurationOrDefault(TencentBlobProviderConfigurationNames.CreateBucketReferer, new List<string>());
set {
if (value == null)
{

38
aspnet-core/framework/cloud-tencent/LINGYUN.Abp.BlobStoring.Tencent/LINGYUN/Abp/BlobStoring/Tencent/TencentCloudBlobProvider.cs

@ -2,6 +2,7 @@
using COSXML.Common;
using COSXML.Model.Bucket;
using COSXML.Model.Object;
using COSXML.Model.Tag;
using LINGYUN.Abp.Tencent.Features;
using System;
using System.Collections.Generic;
@ -67,29 +68,28 @@ public class TencentCloudBlobProvider : BlobProviderBase, ITransientDependency
return null;
}
// TODO: 未经验证
var ossDownloadUrl = ossClient.GetObjectUrl(GetBucketName(args), blobName);
var configuration = args.Configuration.GetTencentConfiguration();
// See: https://cloud.tencent.com/document/product/436/47238
var preSignatureStruct = new PreSignatureStruct
{
appid = configuration.AppId,//"1250000000"; //腾讯云账号 APPID
region = configuration.Region,//"COS_REGION"; //存储桶地域
bucket = GetBucketName(args),//"examplebucket-1250000000"; //存储桶
key = blobName, //对象键
httpMethod = "GET", //HTTP 请求方法
isHttps = true, //生成 HTTPS 请求 URL
signDurationSecond = 600, //请求签名时间为600s
headers = null, //签名中需要校验的 header
queryParameters = null //签名中需要校验的 URL 中请求参数
};
var requestSignURL = ossClient.GenerateSignURL(preSignatureStruct);
var client = HttpClientFactory.CreateTenantOssClient();
var ossContent = await client.GetStreamAsync(ossDownloadUrl);
return ossContent;
return await client.GetStreamAsync(requestSignURL);
}
public override async Task SaveAsync(BlobProviderSaveArgs args)
{
var maxStreamSizeString = await FeatureChecker.GetOrNullAsync(TencentCloudFeatures.BlobStoring.MaximumStreamSize);
if (!"0".Equals(maxStreamSizeString) ||
(int.TryParse(maxStreamSizeString, out var maxStreamSize)
&& (maxStreamSize <= 0
|| maxStreamSize < args.BlobStream.Length / 1024 / 1024)))
{
throw new BusinessException("TencentCloud:10101")
.WithData("Size", maxStreamSizeString);
}
var ossClient = await GetOssClientAsync(args);
var blobName = TencentBlobNameCalculator.Calculate(args);
var configuration = args.Configuration.GetTencentConfiguration();
@ -136,8 +136,8 @@ public class TencentCloudBlobProvider : BlobProviderBase, ITransientDependency
var bucketName = GetBucketName(args);
var request = new PutBucketRequest(bucketName);
// TODO: good! 这很Java
request.SetCosACL(CosACL.PublicReadWrite);
request.SetCosACL(CosACL.Private);
cos.PutBucket(request);

4
aspnet-core/framework/cloud-tencent/LINGYUN.Abp.Tencent/LINGYUN/Abp/Tencent/AbpTencentCloudModule.cs

@ -5,11 +5,15 @@ using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Features;
using Volo.Abp.Settings;
namespace LINGYUN.Abp.Tencent;
[DependsOn(
typeof(AbpCachingModule),
typeof(AbpFeaturesModule),
typeof(AbpSettingsModule),
typeof(AbpJsonModule),
typeof(AbpLocalizationModule))]
public class AbpTencentCloudModule : AbpModule

26
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Aliyun/LINGYUN/Abp/OssManagement/Aliyun/AbpOssManagementAliyunModule.cs

@ -1,4 +1,8 @@
using LINGYUN.Abp.BlobStoring.Aliyun;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using Volo.Abp.BlobStoring;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.OssManagement.Aliyun;
@ -8,4 +12,26 @@ namespace LINGYUN.Abp.OssManagement.Aliyun;
typeof(AbpOssManagementDomainModule))]
public class AbpOssManagementAliyunModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
var ossConfiguration = configuration.GetSection("OssManagement");
var ossProvider = ossConfiguration["Provider"];
if (!ossProvider.IsNullOrWhiteSpace() &&
"Aliyun".Equals(ossProvider, StringComparison.InvariantCultureIgnoreCase))
{
Configure<AbpBlobStoringOptions>(options =>
{
options.Containers.ConfigureAll((containerName, containerConfiguration) =>
{
containerConfiguration.UseAliyun(oss =>
{
ossConfiguration.GetSection("Aliyun").Bind(oss);
});
});
});
context.Services.AddAliyunContainer();
}
}
}

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

@ -1,4 +1,9 @@
using Volo.Abp.BlobStoring.FileSystem;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.IO;
using Volo.Abp.BlobStoring;
using Volo.Abp.BlobStoring.FileSystem;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.OssManagement.FileSystem;
@ -8,4 +13,29 @@ namespace LINGYUN.Abp.OssManagement.FileSystem;
typeof(AbpOssManagementDomainModule))]
public class AbpOssManagementFileSystemModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
var ossConfiguration = configuration.GetSection("OssManagement");
var ossProvider = ossConfiguration["Provider"];
if (!ossProvider.IsNullOrWhiteSpace() &&
"FileSystem".Equals(ossProvider, StringComparison.InvariantCultureIgnoreCase))
{
Configure<AbpBlobStoringOptions>(options =>
{
options.Containers.ConfigureAll((containerName, containerConfiguration) =>
{
containerConfiguration.UseFileSystem(oss =>
{
oss.BasePath = Path.Combine(
Directory.GetCurrentDirectory(),
ossConfiguration["Bucket"] ?? "blobs");
oss.AppendContainerNameToBasePath = ossConfiguration.GetValue("AppendContainerNameToBasePath", true);
});
});
});
context.Services.AddFileSystemContainer();
}
}
}

26
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Minio/LINGYUN/Abp/OssManagement/Minio/AbpOssManagementMinioModule.cs

@ -1,4 +1,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using Volo.Abp.BlobStoring;
using Volo.Abp.BlobStoring.Minio;
using Volo.Abp.Modularity;
@ -11,6 +14,25 @@ public class AbpOssManagementMinioModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddMinioHttpClient();
var configuration = context.Services.GetConfiguration();
var ossConfiguration = configuration.GetSection("OssManagement");
var ossProvider = ossConfiguration["Provider"];
if (!ossProvider.IsNullOrWhiteSpace() &&
"Minio".Equals(ossProvider, StringComparison.InvariantCultureIgnoreCase))
{
context.Services.AddMinioHttpClient();
Configure<AbpBlobStoringOptions>(options =>
{
options.Containers.ConfigureAll((containerName, containerConfiguration) =>
{
containerConfiguration.UseMinio(oss =>
{
ossConfiguration.GetSection("Minio").Bind(oss);
});
});
});
context.Services.AddMinioContainer();
}
}
}

3
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Minio/LINGYUN/Abp/OssManagement/Minio/MinioOssContainer.cs

@ -160,8 +160,7 @@ public class MinioOssContainer : OssContainerBase, IOssObjectExpireor
ID = putResponse.Etag,
Expiration = new Expiration(Clock.Now.Add(request.ExpirationTime.Value))
};
var lifecycleConfiguration = new LifecycleConfiguration();
lifecycleConfiguration.Rules.Add(lifecycleRule);
var lifecycleConfiguration = new LifecycleConfiguration([lifecycleRule]);
var lifecycleArgs = new SetBucketLifecycleArgs()
.WithBucket(bucket)

27
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Nexus/LINGYUN/Abp/OssManagement/Nexus/AbpOssManagementNexusModule.cs

@ -1,6 +1,8 @@
using LINGYUN.Abp.BlobStoring.Nexus;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using Volo.Abp.BlobStoring;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.OssManagement.Nexus;
@ -12,12 +14,25 @@ public class AbpOssManagementNexusModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddTransient<IOssContainerFactory, NexusOssContainerFactory>();
var configuration = context.Services.GetConfiguration();
var ossConfiguration = configuration.GetSection("OssManagement");
var ossProvider = ossConfiguration["Provider"];
context.Services.AddTransient<IOssObjectExpireor>(provider =>
provider
.GetRequiredService<IOssContainerFactory>()
.Create()
.As<NexusOssContainer>());
if (!ossProvider.IsNullOrWhiteSpace() &&
"Nexus".Equals(ossProvider, StringComparison.InvariantCultureIgnoreCase))
{
Configure<AbpBlobStoringOptions>(options =>
{
options.Containers.ConfigureAll((containerName, containerConfiguration) =>
{
containerConfiguration.UseNexus(oss =>
{
ossConfiguration.GetSection("Nexus").Bind(oss);
});
});
});
context.Services.AddNexusContainer();
}
}
}

21
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Nexus/Microsoft/Extensions/DependencyInjection/NexusOssContainerServiceCollectionExtensions.cs

@ -0,0 +1,21 @@
using LINGYUN.Abp.OssManagement;
using LINGYUN.Abp.OssManagement.Nexus;
using System;
namespace Microsoft.Extensions.DependencyInjection;
public static class NexusOssContainerServiceCollectionExtensions
{
public static IServiceCollection AddNexusContainer(this IServiceCollection services)
{
services.AddTransient<IOssContainerFactory, NexusOssContainerFactory>();
services.AddTransient<IOssObjectExpireor>(provider =>
provider
.GetRequiredService<IOssContainerFactory>()
.Create()
.As<NexusOssContainer>());
return services;
}
}

26
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Tencent/LINGYUN/Abp/OssManagement/Tencent/AbpOssManagementTencentModule.cs

@ -1,4 +1,8 @@
using LINGYUN.Abp.BlobStoring.Tencent;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using Volo.Abp.BlobStoring;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.OssManagement.Tencent;
@ -8,4 +12,26 @@ namespace LINGYUN.Abp.OssManagement.Tencent;
typeof(AbpOssManagementDomainModule))]
public class AbpOssManagementTencentModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
var ossConfiguration = configuration.GetSection("OssManagement");
var ossProvider = ossConfiguration["Provider"];
if (!ossProvider.IsNullOrWhiteSpace() &&
"Tencent".Equals(ossProvider, StringComparison.InvariantCultureIgnoreCase))
{
Configure<AbpBlobStoringOptions>(options =>
{
options.Containers.ConfigureAll((containerName, containerConfiguration) =>
{
containerConfiguration.UseTencentCloud(oss =>
{
ossConfiguration.GetSection("Tencent").Bind(oss);
});
});
});
context.Services.AddTencentContainer();
}
}
}

60
aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Tencent/LINGYUN/Abp/OssManagement/Tencent/TencentOssContainer.cs

@ -1,7 +1,10 @@
using COSXML;
using COSXML.Common;
using COSXML.Model.Bucket;
using COSXML.Model.Object;
using COSXML.Model.Service;
using COSXML.Model.Tag;
using COSXML.Transfer;
using LINGYUN.Abp.BlobStoring.Tencent;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
@ -384,35 +387,51 @@ internal class TencentOssContainer : OssContainerBase, IOssObjectExpireor
// throw new ContainerNotFoundException($"Can't not found object {objectName} in container {request.Bucket} with aliyun blob storing");
}
var getObjectRequest = new GetObjectBytesRequest(request.Bucket, objectName);
if (!request.Process.IsNullOrWhiteSpace())
{
getObjectRequest.SetQueryParameter(request.Process, null);
}
var objectResult = ossClient.GetObject(getObjectRequest);
var objectDownloadUrl = ossClient.GetObjectUrl(request.Bucket, objectName);
var client = HttpClientFactory.CreateTenantOssClient();
var objectContent = await client.GetStreamAsync(objectDownloadUrl);
var headObjectRequest = new HeadObjectRequest(request.Bucket, objectName);
var headObjectResult = ossClient.HeadObject(headObjectRequest);
var ossObject = new OssObject(
!objectPath.IsNullOrWhiteSpace()
? objectResult.Key.Replace(objectPath, "")
: objectResult.Key,
? headObjectResult.Key.Replace(objectPath, "")
: headObjectResult.Key,
request.Path,
objectResult.eTag,
headObjectResult.eTag,
null,
objectContent.Length,
headObjectResult.size,
null,
new Dictionary<string, string>(),
objectResult.Key.EndsWith("/"))
headObjectResult.Key.EndsWith("/"))
{
FullName = objectResult.Key
FullName = headObjectResult.Key
};
if (objectContent.Length > 0)
if (headObjectResult.size > 0)
{
ossObject.SetContent(objectContent);
var configuration = await GetConfigurationAsync();
// See: https://cloud.tencent.com/document/product/436/47238
var preSignatureStruct = new PreSignatureStruct
{
appid = configuration.AppId,//"1250000000"; //腾讯云账号 APPID
region = configuration.Region,//"COS_REGION"; //存储桶地域
bucket = request.Bucket,//"examplebucket-1250000000"; //存储桶
key = objectName, //对象键
httpMethod = "GET", //HTTP 请求方法
isHttps = true, //生成 HTTPS 请求 URL
signDurationSecond = 600, //请求签名时间为600s
headers = null, //签名中需要校验的 header
queryParameters = null //签名中需要校验的 URL 中请求参数
};
if (!request.Process.IsNullOrWhiteSpace())
{
preSignatureStruct.queryParameters = new Dictionary<string, string>
{
{ request.Process, "" }
};
}
var requestSignURL = ossClient.GenerateSignURL(preSignatureStruct);
var client = HttpClientFactory.CreateTenantOssClient();
ossObject.SetContent(await client.GetStreamAsync(requestSignURL));
}
return ossObject;
@ -447,6 +466,11 @@ internal class TencentOssContainer : OssContainerBase, IOssObjectExpireor
return cos.DoesObjectExist(request);
}
protected async virtual Task<TencentBlobProviderConfiguration> GetConfigurationAsync()
{
return await CosClientFactory.GetConfigurationAsync<AbpOssManagementContainer>();
}
protected async virtual Task<CosXml> CreateClientAsync()
{
return await CosClientFactory.CreateAsync<AbpOssManagementContainer>();

7
aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/appsettings.Development.json

@ -108,6 +108,13 @@
"Elasticsearch": {
"NodeUris": "http://127.0.0.1:9200"
},
"OssManagement": {
"Provider": "FileSystem",
"FileSystem": {
"Bucket": "blobs",
"AppendContainerNameToBasePath": true
}
},
"Serilog": {
"MinimumLevel": {
"Default": "Information",

Loading…
Cancel
Save