mirror of https://github.com/abpframework/abp.git
24 changed files with 762 additions and 11 deletions
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,27 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<AssemblyName>Volo.Abp.BlobStoring.Aliyun</AssemblyName> |
|||
<PackageId>Volo.Abp.BlobStoring.Aliyun</PackageId> |
|||
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> |
|||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
|||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
|||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="aliyun-net-sdk-sts" Version="3.0.4" /> |
|||
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.10.0" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\Volo.Abp.BlobStoring\Volo.Abp.BlobStoring.csproj" /> |
|||
<ProjectReference Include="..\Volo.Abp.Caching\Volo.Abp.Caching.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,17 @@ |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.BlobStoring.Aliyun |
|||
{ |
|||
/// <summary>
|
|||
/// https://help.aliyun.com/document_detail/31817.html
|
|||
/// </summary>
|
|||
[DependsOn( |
|||
typeof(AbpBlobStoringModule), |
|||
typeof(AbpCachingModule) |
|||
)] |
|||
public class AbpBlobStoringAliyunModule: AbpModule |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
using System; |
|||
|
|||
namespace Volo.Abp.BlobStoring.Aliyun |
|||
{ |
|||
public static class AliyunBlobContainerConfigurationExtensions |
|||
{ |
|||
public static AliyunBlobProviderConfiguration GetAliyunConfiguration( |
|||
this BlobContainerConfiguration containerConfiguration) |
|||
{ |
|||
return new AliyunBlobProviderConfiguration(containerConfiguration); |
|||
} |
|||
|
|||
public static BlobContainerConfiguration UseAliyun( |
|||
this BlobContainerConfiguration containerConfiguration, |
|||
Action<AliyunBlobProviderConfiguration> aliyunConfigureAction) |
|||
{ |
|||
containerConfiguration.ProviderType = typeof(AliyunBlobProvider); |
|||
containerConfiguration.NamingNormalizers.TryAdd<AliyunBlobNamingNormalizer>(); |
|||
|
|||
aliyunConfigureAction(new AliyunBlobProviderConfiguration(containerConfiguration)); |
|||
|
|||
return containerConfiguration; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,56 @@ |
|||
using System.Text.RegularExpressions; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.BlobStoring.Aliyun |
|||
{ |
|||
public class AliyunBlobNamingNormalizer : IBlobNamingNormalizer, ITransientDependency |
|||
{ |
|||
/// <summary>
|
|||
/// 只允许小写字母、数字、短横线(-),且不能以短横线开头或结尾
|
|||
/// Container names can contain only letters, numbers, and the dash (-) character
|
|||
/// can't start or end with the dash (-) character
|
|||
/// 3~63 个字符
|
|||
/// Container names must be from 3 through 63 characters long
|
|||
/// </summary>
|
|||
public virtual string NormalizeContainerName(string containerName) |
|||
{ |
|||
// All letters in a container name must be lowercase.
|
|||
containerName = containerName.ToLower(); |
|||
|
|||
// Container names can contain only letters, numbers, and the dash (-) character.
|
|||
containerName = Regex.Replace(containerName, "[^a-z0-9-]", string.Empty); |
|||
|
|||
// Every dash (-) character must be immediately preceded and followed by a letter or number;
|
|||
// consecutive dashes are not permitted in container names.
|
|||
// Container names must start or end with a letter or number
|
|||
containerName = Regex.Replace(containerName, "-{2,}", "-"); |
|||
containerName = Regex.Replace(containerName, "^-", string.Empty); |
|||
containerName = Regex.Replace(containerName, "-$", string.Empty); |
|||
|
|||
// Container names must be from 3 through 63 characters long.
|
|||
if (containerName.Length < 3) |
|||
{ |
|||
var length = containerName.Length; |
|||
for (var i = 0; i < 3 - length; i++) |
|||
{ |
|||
containerName += "0"; |
|||
} |
|||
} |
|||
|
|||
if (containerName.Length > 63) |
|||
{ |
|||
containerName = containerName.Substring(0, 63); |
|||
} |
|||
|
|||
// can't start or end with the dash (-) character
|
|||
containerName = containerName.Trim('-'); |
|||
|
|||
return containerName; |
|||
} |
|||
|
|||
public virtual string NormalizeBlobName(string blobName) |
|||
{ |
|||
return blobName; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,81 @@ |
|||
using Aliyun.OSS; |
|||
using System.IO; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.BlobStoring.Aliyun |
|||
{ |
|||
public class AliyunBlobProvider : BlobProviderBase, ITransientDependency |
|||
{ |
|||
protected IOssClientFactory OssClientFactory { get; } |
|||
protected IAliyunBlobNameCalculator AliyunBlobNameCalculator { get; } |
|||
|
|||
public AliyunBlobProvider( |
|||
IOssClientFactory ossClientFactory, |
|||
IAliyunBlobNameCalculator aliyunBlobNameCalculator) |
|||
{ |
|||
OssClientFactory = ossClientFactory; |
|||
AliyunBlobNameCalculator = aliyunBlobNameCalculator; |
|||
} |
|||
|
|||
private IOss GetOssClient(BlobContainerConfiguration blobContainerConfiguration) |
|||
{ |
|||
var aliyunConfig = blobContainerConfiguration.GetAliyunConfiguration(); |
|||
return OssClientFactory.Create(aliyunConfig); |
|||
} |
|||
|
|||
private IOss GetOssClient(AliyunBlobProviderConfiguration aliyunConfig) |
|||
{ |
|||
return OssClientFactory.Create(aliyunConfig); |
|||
} |
|||
|
|||
public override async Task SaveAsync(BlobProviderSaveArgs args) |
|||
{ |
|||
var blobName = AliyunBlobNameCalculator.Calculate(args); |
|||
if (!args.OverrideExisting && await ExistsAsync(new BlobProviderExistsArgs(args.ContainerName, args.Configuration, args.BlobName))) |
|||
{ |
|||
throw new BlobAlreadyExistsException($"Saving BLOB '{args.BlobName}' does already exists in the container '{args.ContainerName}'! Set {nameof(args.OverrideExisting)} if it should be overwritten."); |
|||
} |
|||
var aliyunConfig = args.Configuration.GetAliyunConfiguration(); |
|||
var OssClient = GetOssClient(aliyunConfig); |
|||
if (aliyunConfig.CreateContainerIfNotExists) |
|||
{ |
|||
if (!OssClient.DoesBucketExist(args.ContainerName)) |
|||
{ |
|||
OssClient.CreateBucket(args.ContainerName); |
|||
} |
|||
} |
|||
OssClient.PutObject(args.ContainerName, blobName, args.BlobStream); |
|||
} |
|||
|
|||
public override Task<bool> DeleteAsync(BlobProviderDeleteArgs args) |
|||
{ |
|||
var blobName = AliyunBlobNameCalculator.Calculate(args); |
|||
var OssClient = GetOssClient(args.Configuration); |
|||
var result = OssClient.DeleteObject(args.ContainerName, blobName); |
|||
//TODO: undifend delete flag
|
|||
//https://help.aliyun.com/document_detail/91924.html
|
|||
return Task.FromResult(true); |
|||
} |
|||
|
|||
public override Task<bool> ExistsAsync(BlobProviderExistsArgs args) |
|||
{ |
|||
var blobName = AliyunBlobNameCalculator.Calculate(args); |
|||
var OssClient = GetOssClient(args.Configuration); |
|||
return Task.FromResult(OssClient.DoesObjectExist(args.ContainerName, blobName)); |
|||
} |
|||
|
|||
public override async Task<Stream> GetOrNullAsync(BlobProviderGetArgs args) |
|||
{ |
|||
var blobName = AliyunBlobNameCalculator.Calculate(args); |
|||
|
|||
var OssClient = GetOssClient(args.Configuration); |
|||
if (!await ExistsAsync(new BlobProviderExistsArgs(args.ContainerName, args.Configuration, args.BlobName))) |
|||
{ |
|||
return null; |
|||
} |
|||
var result = OssClient.GetObject(args.ContainerName, blobName); |
|||
return result.Content; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,96 @@ |
|||
using System; |
|||
|
|||
namespace Volo.Abp.BlobStoring.Aliyun |
|||
{ |
|||
/// <summary>
|
|||
/// STS临时授权访问OSS:https://help.aliyun.com/document_detail/100624.html
|
|||
/// </summary>
|
|||
public class AliyunBlobProviderConfiguration |
|||
{ |
|||
public string AccessKeyId |
|||
{ |
|||
get => _containerConfiguration.GetConfiguration<string>(AliyunBlobProviderConfigurationNames.AccessKeyId); |
|||
set => _containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.AccessKeyId, Check.NotNullOrWhiteSpace(value, nameof(value))); |
|||
} |
|||
|
|||
public string AccessKeySecret |
|||
{ |
|||
get => _containerConfiguration.GetConfiguration<string>(AliyunBlobProviderConfigurationNames.AccessKeySecret); |
|||
set => _containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.AccessKeySecret, Check.NotNullOrWhiteSpace(value, nameof(value))); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// https://help.aliyun.com/document_detail/31837.html
|
|||
/// eg: https://oss-cn-beijing.aliyuncs.com
|
|||
/// </summary>
|
|||
public string Endpoint |
|||
{ |
|||
get => _containerConfiguration.GetConfiguration<string>(AliyunBlobProviderConfigurationNames.Endpoint); |
|||
set => _containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.Endpoint, Check.NotNullOrWhiteSpace(value, nameof(value))); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// STS https://help.aliyun.com/document_detail/66053.html
|
|||
/// eg:cn-beijing
|
|||
/// </summary>
|
|||
public string RegionId |
|||
{ |
|||
get => _containerConfiguration.GetConfiguration<string>(AliyunBlobProviderConfigurationNames.RegionId); |
|||
set => _containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.RegionId, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// eg:acs:ram::$accountID:role/$roleName
|
|||
/// </summary>
|
|||
public string RoleArn |
|||
{ |
|||
get => _containerConfiguration.GetConfiguration<string>(AliyunBlobProviderConfigurationNames.RoleArn); |
|||
set => _containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.RoleArn, value); |
|||
} |
|||
|
|||
public string RoleSessionName |
|||
{ |
|||
get => _containerConfiguration.GetConfiguration<string>(AliyunBlobProviderConfigurationNames.RoleSessionName); |
|||
set => _containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.RoleSessionName, value); |
|||
} |
|||
|
|||
public int DurationSeconds |
|||
{ |
|||
get => _containerConfiguration.GetConfigurationOrDefault(AliyunBlobProviderConfigurationNames.DurationSeconds, 0); |
|||
set => _containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.DurationSeconds, value); |
|||
} |
|||
|
|||
public string Policy |
|||
{ |
|||
get => _containerConfiguration.GetConfiguration<string>(AliyunBlobProviderConfigurationNames.Policy); |
|||
set => _containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.Policy, value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Default value: false.
|
|||
/// </summary>
|
|||
public bool CreateContainerIfNotExists |
|||
{ |
|||
get => _containerConfiguration.GetConfigurationOrDefault(AliyunBlobProviderConfigurationNames.CreateContainerIfNotExists, false); |
|||
set => _containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.CreateContainerIfNotExists, value); |
|||
} |
|||
|
|||
private readonly BlobContainerConfiguration _containerConfiguration; |
|||
|
|||
public AliyunBlobProviderConfiguration(BlobContainerConfiguration containerConfiguration) |
|||
{ |
|||
_containerConfiguration = containerConfiguration; |
|||
} |
|||
|
|||
public string ToOssKeyString() |
|||
{ |
|||
Uri uPoint = new Uri(Endpoint); |
|||
return $"memorycache:aliyun:id:{AccessKeyId},sec:{AccessKeySecret},ept:{uPoint.Host.ToLower()}"; |
|||
} |
|||
|
|||
public string ToOssWithStsKeyString() |
|||
{ |
|||
return ToOssKeyString() + $",rid:{RegionId},ra:{RoleArn},rsn:{RoleSessionName},pl:{Policy}"; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
namespace Volo.Abp.BlobStoring.Aliyun |
|||
{ |
|||
public class AliyunBlobProviderConfigurationNames |
|||
{ |
|||
public const string AccessKeyId = "Aliyun.AccessKeyId"; |
|||
public const string AccessKeySecret = "Aliyun.AccessKeySecret"; |
|||
public const string Endpoint = "Aliyun.Endpoint"; |
|||
public const string RegionId = "Aliyun.RegionId"; |
|||
public const string RoleArn = "Aliyun.RoleArn"; |
|||
public const string RoleSessionName = "Aliyun.RoleSessionName"; |
|||
public const string DurationSeconds = "Aliyun.DurationSeconds"; |
|||
public const string Policy = "Aliyun.Policy"; |
|||
public const string CreateContainerIfNotExists = "Aliyun.CreateContainerIfNotExists"; |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace Volo.Abp.BlobStoring.Aliyun |
|||
{ |
|||
public class DefaultAliyunBlobNameCalculator: IAliyunBlobNameCalculator, ITransientDependency |
|||
{ |
|||
protected ICurrentTenant CurrentTenant { get; } |
|||
|
|||
public DefaultAliyunBlobNameCalculator(ICurrentTenant currentTenant) |
|||
{ |
|||
CurrentTenant = currentTenant; |
|||
} |
|||
|
|||
public virtual string Calculate(BlobProviderArgs args) |
|||
{ |
|||
return CurrentTenant.Id == null |
|||
? $"host/{args.BlobName}" |
|||
: $"tenants/{CurrentTenant.Id.Value:D}/{args.BlobName}"; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,77 @@ |
|||
using Aliyun.Acs.Core; |
|||
using Aliyun.Acs.Core.Auth.Sts; |
|||
using Aliyun.Acs.Core.Http; |
|||
using Aliyun.Acs.Core.Profile; |
|||
using Aliyun.OSS; |
|||
using Microsoft.Extensions.Caching.Memory; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.BlobStoring.Aliyun |
|||
{ |
|||
/// <summary>
|
|||
/// STS:https://help.aliyun.com/document_detail/28756.html
|
|||
/// STS or sub account number
|
|||
/// </summary>
|
|||
public class DefaultOssClientFactory : IOssClientFactory, ITransientDependency |
|||
{ |
|||
private readonly IBlobContainerConfigurationProvider _configurationProvider; |
|||
private readonly IMemoryCache _cache; |
|||
public DefaultOssClientFactory( |
|||
IBlobContainerConfigurationProvider configurationProvider, |
|||
IMemoryCache cache) |
|||
{ |
|||
_configurationProvider = configurationProvider; |
|||
_cache = cache; |
|||
} |
|||
|
|||
public virtual IOss Create(AliyunBlobProviderConfiguration aliyunConfig) |
|||
{ |
|||
//使用账号 sub account number
|
|||
if (aliyunConfig.DurationSeconds <= 0) |
|||
{ |
|||
var key = aliyunConfig.ToOssKeyString(); |
|||
var iOssClient = _cache.Get<IOss>(key); |
|||
if (iOssClient != null) |
|||
{ |
|||
return iOssClient; |
|||
} |
|||
iOssClient = new OssClient(aliyunConfig.Endpoint, aliyunConfig.AccessKeyId, aliyunConfig.AccessKeySecret); |
|||
_cache.Set(key, iOssClient); |
|||
return iOssClient; |
|||
} |
|||
else |
|||
{ |
|||
//使用STS
|
|||
var key = aliyunConfig.ToOssWithStsKeyString(); |
|||
var iOssClient = _cache.Get<IOss>(key); |
|||
if (iOssClient != null) |
|||
{ |
|||
return iOssClient; |
|||
} |
|||
IClientProfile profile = DefaultProfile.GetProfile( |
|||
aliyunConfig.RegionId, |
|||
aliyunConfig.AccessKeyId, |
|||
aliyunConfig.AccessKeySecret); |
|||
DefaultAcsClient client = new DefaultAcsClient(profile); |
|||
//构建AssumeRole请求
|
|||
AssumeRoleRequest request = new AssumeRoleRequest |
|||
{ |
|||
AcceptFormat = FormatType.JSON, |
|||
//指定角色ARN
|
|||
RoleArn = aliyunConfig.RoleArn, |
|||
RoleSessionName = aliyunConfig.RoleSessionName, |
|||
//设置Token有效期,可选参数,默认3600秒
|
|||
DurationSeconds = aliyunConfig.DurationSeconds, |
|||
//设置Token的附加权限策略;在获取Token时,通过额外设置一个权限策略进一步减小Token的权限
|
|||
Policy = aliyunConfig.Policy.IsNullOrEmpty() ? null : aliyunConfig.Policy, |
|||
}; |
|||
var response = client.GetAcsResponse(request); |
|||
iOssClient = new OssClient(aliyunConfig.Endpoint, response.Credentials.AccessKeyId, response.Credentials.AccessKeySecret, response.Credentials.SecurityToken); |
|||
_cache.Set(key, iOssClient, TimeSpan.FromSeconds(aliyunConfig.DurationSeconds)); |
|||
return iOssClient; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
namespace Volo.Abp.BlobStoring.Aliyun |
|||
{ |
|||
public interface IAliyunBlobNameCalculator |
|||
{ |
|||
string Calculate(BlobProviderArgs args); |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using Aliyun.OSS; |
|||
|
|||
namespace Volo.Abp.BlobStoring.Aliyun |
|||
{ |
|||
public interface IOssClientFactory |
|||
{ |
|||
IOss Create(AliyunBlobProviderConfiguration args); |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
{ |
|||
"dependencies": { |
|||
"secrets1": { |
|||
"type": "secrets" |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
{ |
|||
"dependencies": { |
|||
"secrets1": { |
|||
"type": "secrets.user" |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\common.test.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netcoreapp3.1</TargetFramework> |
|||
<RootNamespace /> |
|||
<UserSecretsId>fe9a87da-3584-40e0-a06c-aa499936015d</UserSecretsId> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\src\Volo.Abp.BlobStoring.Aliyun\Volo.Abp.BlobStoring.Aliyun.csproj" /> |
|||
<ProjectReference Include="..\..\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" /> |
|||
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" /> |
|||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="3.1.5" /> |
|||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" /> |
|||
<ProjectReference Include="..\Volo.Abp.BlobStoring.Tests\Volo.Abp.BlobStoring.Tests.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,19 @@ |
|||
using Volo.Abp.Testing; |
|||
|
|||
namespace Volo.Abp.BlobStoring.Aliyun |
|||
{ |
|||
public class AbpBlobStoringAliyunTestCommonBase : AbpIntegratedTest<AbpBlobStoringAliyunTestCommonModule> |
|||
{ |
|||
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) |
|||
{ |
|||
options.UseAutofac(); |
|||
} |
|||
} |
|||
public class AbpBlobStoringAliyunTestBase : AbpIntegratedTest<AbpBlobStoringAliyunTestModule> |
|||
{ |
|||
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) |
|||
{ |
|||
options.UseAutofac(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,65 @@ |
|||
using Microsoft.Extensions.Configuration; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using System; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace Volo.Abp.BlobStoring.Aliyun |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// This module will not try to connect to azure.
|
|||
/// </summary>
|
|||
[DependsOn( |
|||
typeof(AbpBlobStoringAliyunModule), |
|||
typeof(AbpBlobStoringTestModule) |
|||
)] |
|||
public class AbpBlobStoringAliyunTestCommonModule : AbpModule |
|||
{ |
|||
|
|||
} |
|||
|
|||
[DependsOn( |
|||
typeof(AbpBlobStoringAliyunTestCommonModule) |
|||
)] |
|||
public class AbpBlobStoringAliyunTestModule : AbpModule |
|||
{ |
|||
private const string UserSecretsId = "fe9a87da-3584-40e0-a06c-aa499936015d"; |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.ReplaceConfiguration(ConfigurationHelper.BuildConfiguration(builderAction: builder => |
|||
{ |
|||
builder.AddUserSecrets(UserSecretsId); |
|||
})); |
|||
|
|||
var configuration = context.Services.GetConfiguration(); |
|||
var _accessKeyId = configuration["Aliyun:AccessKeyId"]; |
|||
var _accessKeySecret = configuration["Aliyun:AccessKeySecret"]; |
|||
var _endpoint = configuration["Aliyun:Endpoint"]; |
|||
var _regionId = configuration["Aliyun:RegionId"]; |
|||
var _roleArn = configuration["Aliyun:RoleArn"]; |
|||
|
|||
Configure<AbpBlobStoringOptions>(options => |
|||
{ |
|||
options.Containers.ConfigureAll((containerName, containerConfiguration) => |
|||
{ |
|||
containerConfiguration.UseAliyun(aliyun => |
|||
{ |
|||
aliyun.AccessKeyId = _accessKeyId; |
|||
aliyun.AccessKeySecret = _accessKeySecret; |
|||
aliyun.Endpoint = _endpoint;//eg:https://oss-cn-beijing.aliyuncs.com
|
|||
//STS
|
|||
aliyun.RegionId = _regionId;//eg:cn-beijing
|
|||
aliyun.RoleArn = _roleArn;//eg:acs:ram::1320235309887297:role/role-oss-xxxxx
|
|||
aliyun.RoleSessionName = Guid.NewGuid().ToString("N"); |
|||
aliyun.DurationSeconds = 3600; |
|||
aliyun.Policy = String.Empty; |
|||
//Other
|
|||
aliyun.CreateContainerIfNotExists = true; |
|||
}); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
using Shouldly; |
|||
using System.IO; |
|||
using System.Text; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.BlobStoring.Aliyun |
|||
{ |
|||
public class AliyunBlobContainer_Tests : BlobContainer_Tests<AbpBlobStoringAliyunTestModule> |
|||
{ |
|||
private readonly IBlobContainer<MyTestContainer> _blobContainer; |
|||
private readonly string _blobname = "my-blob"; |
|||
private readonly string _stringContent = "my-blob-content"; |
|||
public AliyunBlobContainer_Tests() |
|||
{ |
|||
_blobContainer = GetRequiredService<IBlobContainer<MyTestContainer>>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public async void BlobContainer_Test() |
|||
{ |
|||
var streamContent = Encoding.Default.GetBytes(_stringContent); |
|||
await _blobContainer.SaveAsync(_blobname, streamContent, true); |
|||
var streamData = await _blobContainer.GetAsync(_blobname); |
|||
var tfExist = await _blobContainer.ExistsAsync(_blobname); |
|||
if (tfExist) |
|||
{ |
|||
await _blobContainer.DeleteAsync(_blobname); |
|||
} |
|||
StreamReader reader = new StreamReader(streamData); |
|||
var stringData = reader.ReadToEnd();// Encoding.Default.GetString(bytes);
|
|||
stringData.ShouldBe(_stringContent); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,55 @@ |
|||
using Shouldly; |
|||
using System; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.BlobStoring.Aliyun |
|||
{ |
|||
public class AliyunBlobNameCalculator_Tests: AbpBlobStoringAliyunTestCommonBase |
|||
{ |
|||
private readonly IAliyunBlobNameCalculator _calculator; |
|||
private readonly ICurrentTenant _currentTenant; |
|||
|
|||
private const string AliyunSeparator = "/"; |
|||
|
|||
public AliyunBlobNameCalculator_Tests() |
|||
{ |
|||
_calculator = GetRequiredService<IAliyunBlobNameCalculator>(); |
|||
_currentTenant = GetRequiredService<ICurrentTenant>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Default_Settings() |
|||
{ |
|||
_calculator.Calculate( |
|||
GetArgs("my-container", "my-blob") |
|||
).ShouldBe($"host{AliyunSeparator}my-blob"); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Default_Settings_With_TenantId() |
|||
{ |
|||
var tenantId = Guid.NewGuid(); |
|||
|
|||
using (_currentTenant.Change(tenantId)) |
|||
{ |
|||
_calculator.Calculate( |
|||
GetArgs("my-container", "my-blob") |
|||
).ShouldBe($"tenants{AliyunSeparator}{tenantId:D}{AliyunSeparator}my-blob"); |
|||
} |
|||
} |
|||
|
|||
private static BlobProviderArgs GetArgs( |
|||
string containerName, |
|||
string blobName) |
|||
{ |
|||
return new BlobProviderGetArgs( |
|||
containerName, |
|||
new BlobContainerConfiguration().UseAliyun(x => |
|||
{ |
|||
}), |
|||
blobName |
|||
); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,57 @@ |
|||
using Shouldly; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.BlobStoring.Aliyun |
|||
{ |
|||
public class DefaultAliyunBlobNamingNormalizerProvider_Tests: AbpBlobStoringAliyunTestCommonBase |
|||
{ |
|||
private readonly IBlobNamingNormalizer _blobNamingNormalizer; |
|||
|
|||
public DefaultAliyunBlobNamingNormalizerProvider_Tests() |
|||
{ |
|||
_blobNamingNormalizer = GetRequiredService<IBlobNamingNormalizer>(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void NormalizeContainerName_Lowercase() |
|||
{ |
|||
var filename = "ThisIsMyContainerName"; |
|||
filename = _blobNamingNormalizer.NormalizeContainerName(filename); |
|||
filename.ShouldBe("thisismycontainername"); |
|||
} |
|||
|
|||
[Fact] |
|||
public void NormalizeContainerName_Only_Letters_Numbers_Dash() |
|||
{ |
|||
var filename = ",./this-i,./s-my-c,./ont,./ai+*/.=!@#$n^&*er-name.+/"; |
|||
filename = _blobNamingNormalizer.NormalizeContainerName(filename); |
|||
filename.ShouldBe("this-is-my-container-name"); |
|||
} |
|||
|
|||
[Fact] |
|||
public void NormalizeContainerName_Dash() |
|||
{ |
|||
var filename = "-this--is----my-container----name-"; |
|||
filename = _blobNamingNormalizer.NormalizeContainerName(filename); |
|||
filename.ShouldBe("this-is-my-container-name"); |
|||
} |
|||
|
|||
|
|||
[Fact] |
|||
public void NormalizeContainerName_Min_Length() |
|||
{ |
|||
var filename = "a"; |
|||
filename = _blobNamingNormalizer.NormalizeContainerName(filename); |
|||
filename.Length.ShouldBeGreaterThanOrEqualTo(3); |
|||
} |
|||
|
|||
|
|||
[Fact] |
|||
public void NormalizeContainerName_Max_Length() |
|||
{ |
|||
var filename = "abpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabpabp"; |
|||
filename = _blobNamingNormalizer.NormalizeContainerName(filename); |
|||
filename.Length.ShouldBeLessThanOrEqualTo(63); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
namespace Volo.Abp.BlobStoring.Aliyun |
|||
{ |
|||
[BlobContainerName("my-container")] |
|||
public class MyTestContainer |
|||
{ |
|||
} |
|||
} |
|||
Loading…
Reference in new issue