23 changed files with 695 additions and 12 deletions
@ -0,0 +1,12 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.Core" Version="2.9.0" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,15 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.Aliyun.Authorization |
|||
{ |
|||
public class AbpAliyunAuthorizationModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
var configuration = context.Services.GetConfiguration(); |
|||
|
|||
Configure<AbpAliyunOptions>(configuration.GetSection("Aliyun:Auth")); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
namespace LINGYUN.Abp.Aliyun.Authorization |
|||
{ |
|||
public class AbpAliyunOptions |
|||
{ |
|||
/// <summary>
|
|||
/// 访问标识
|
|||
/// </summary>
|
|||
public string AccessKeyId { get; set; } |
|||
/// <summary>
|
|||
/// 访问密钥
|
|||
/// </summary>
|
|||
public string AccessKeySecret { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<RootNamespace /> |
|||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> |
|||
<Version>2.9.0</Version> |
|||
<Authors>LINGYUN</Authors> |
|||
<Description>阿里云Oss对象存储Abp集成</Description> |
|||
</PropertyGroup> |
|||
|
|||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> |
|||
<OutputPath>D:\LocalNuget</OutputPath> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.10.0" /> |
|||
<PackageReference Include="Volo.Abp.BlobStoring" Version="2.9.0" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.Aliyun.Authorization\LINGYUN.Abp.Aliyun.Authorization.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,35 @@ |
|||
using LINGYUN.Abp.Aliyun.Authorization; |
|||
using Microsoft.Extensions.Configuration; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using System.Collections.Generic; |
|||
using Volo.Abp.BlobStoring; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.BlobStoring.Aliyun |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpBlobStoringModule), |
|||
typeof(AbpAliyunAuthorizationModule))] |
|||
public class AbpBlobStoringAliyunModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
var configuration = context.Services.GetConfiguration(); |
|||
|
|||
Configure<AbpBlobStoringOptions>(options => |
|||
{ |
|||
context.Services.ExecutePreConfiguredActions(options); |
|||
options.Containers.ConfigureAll((containerName, containerConfiguration) => |
|||
{ |
|||
containerConfiguration.UseAliyun(aliyun => |
|||
{ |
|||
aliyun.BucketName = configuration[AliyunBlobProviderConfigurationNames.BucketName]; |
|||
aliyun.CreateBucketIfNotExists = configuration.GetSection(AliyunBlobProviderConfigurationNames.CreateBucketIfNotExists).Get<bool>(); |
|||
aliyun.CreateBucketReferer = configuration.GetSection(AliyunBlobProviderConfigurationNames.CreateBucketReferer).Get<List<string>>(); |
|||
aliyun.Endpoint = configuration[AliyunBlobProviderConfigurationNames.Endpoint]; |
|||
}); |
|||
}); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
using System; |
|||
using Volo.Abp.BlobStoring; |
|||
|
|||
namespace LINGYUN.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); |
|||
|
|||
aliyunConfigureAction(new AliyunBlobProviderConfiguration(containerConfiguration)); |
|||
|
|||
return containerConfiguration; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,148 @@ |
|||
using Aliyun.OSS; |
|||
using LINGYUN.Abp.Aliyun.Authorization; |
|||
using Microsoft.Extensions.Options; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.BlobStoring; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace LINGYUN.Abp.BlobStoring.Aliyun |
|||
{ |
|||
public class AliyunBlobProvider : BlobProviderBase, ITransientDependency |
|||
{ |
|||
protected AbpAliyunOptions Options { get; } |
|||
protected IAliyunBlobNameCalculator AliyunBlobNameCalculator { get; } |
|||
|
|||
public AliyunBlobProvider( |
|||
IOptions<AbpAliyunOptions> options, |
|||
IAliyunBlobNameCalculator aliyunBlobNameCalculator) |
|||
{ |
|||
Options = options.Value; |
|||
AliyunBlobNameCalculator = aliyunBlobNameCalculator; |
|||
} |
|||
|
|||
public override async Task<bool> DeleteAsync(BlobProviderDeleteArgs args) |
|||
{ |
|||
var blobName = AliyunBlobNameCalculator.Calculate(args); |
|||
|
|||
if (await BlobExistsAsync(args, blobName)) |
|||
{ |
|||
var ossClient = GetOssClient(args); |
|||
|
|||
return ossClient.DeleteObject(GetBucketName(args), blobName).DeleteMarker; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public override async Task<bool> ExistsAsync(BlobProviderExistsArgs args) |
|||
{ |
|||
var blobName = AliyunBlobNameCalculator.Calculate(args); |
|||
|
|||
return await BlobExistsAsync(args, blobName); |
|||
} |
|||
|
|||
public override async Task<Stream> GetOrNullAsync(BlobProviderGetArgs args) |
|||
{ |
|||
var blobName = AliyunBlobNameCalculator.Calculate(args); |
|||
|
|||
if (!await BlobExistsAsync(args, blobName)) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
var ossClient = GetOssClient(args); |
|||
var ossObject = ossClient.GetObject(GetBucketName(args), blobName); |
|||
// 返回原始结果才会调用 Stream.ReadAsync();
|
|||
return ossObject.Content; |
|||
} |
|||
|
|||
public override async Task SaveAsync(BlobProviderSaveArgs args) |
|||
{ |
|||
var blobName = AliyunBlobNameCalculator.Calculate(args); |
|||
var configuration = args.Configuration.GetAliyunConfiguration(); |
|||
if (!args.OverrideExisting && await BlobExistsAsync(args, blobName)) |
|||
{ |
|||
throw new BlobAlreadyExistsException($"Saving BLOB '{args.BlobName}' does already exists in the bucketName '{GetBucketName(args)}'! Set {nameof(args.OverrideExisting)} if it should be overwritten."); |
|||
} |
|||
|
|||
if (configuration.CreateBucketIfNotExists) |
|||
{ |
|||
await CreateBucketIfNotExists(args, configuration.CreateBucketReferer); |
|||
} |
|||
|
|||
var bucketName = GetBucketName(args); |
|||
var ossClient = GetOssClient(args); |
|||
|
|||
if (args.OverrideExisting && await BlobExistsAsync(args, blobName)) |
|||
{ |
|||
ossClient.DeleteObject(bucketName, blobName); |
|||
} |
|||
|
|||
ossClient.PutObject(bucketName, blobName, args.BlobStream); |
|||
} |
|||
|
|||
protected virtual OssClient GetOssClient(BlobProviderArgs args) |
|||
{ |
|||
var configuration = args.Configuration.GetAliyunConfiguration(); |
|||
var ossClient = new OssClient(configuration.Endpoint, Options.AccessKeyId, Options.AccessKeySecret); |
|||
return ossClient; |
|||
} |
|||
|
|||
protected virtual async Task CreateBucketIfNotExists(BlobProviderArgs args, IList<string> refererList = null) |
|||
{ |
|||
if (! await BucketExistsAsync(args)) |
|||
{ |
|||
var ossClient = GetOssClient(args); |
|||
var bucketName = GetBucketName(args); |
|||
|
|||
var request = new CreateBucketRequest(bucketName) |
|||
{ |
|||
//设置存储空间访问权限ACL。
|
|||
ACL = CannedAccessControlList.PublicReadWrite, |
|||
//设置数据容灾类型。
|
|||
DataRedundancyType = DataRedundancyType.ZRS |
|||
}; |
|||
|
|||
ossClient.CreateBucket(request); |
|||
|
|||
if (refererList != null && refererList.Count > 0) |
|||
{ |
|||
var srq = new SetBucketRefererRequest(bucketName, refererList); |
|||
ossClient.SetBucketReferer(srq); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private async Task<bool> BlobExistsAsync(BlobProviderArgs args, string blobName) |
|||
{ |
|||
var ossClient = GetOssClient(args); |
|||
var bucketExists = await BucketExistsAsync(args); |
|||
if (bucketExists) |
|||
{ |
|||
var objectExists = ossClient.DoesObjectExist(GetBucketName(args), blobName); |
|||
|
|||
return objectExists; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
private Task<bool> BucketExistsAsync(BlobProviderArgs args) |
|||
{ |
|||
var ossClient = GetOssClient(args); |
|||
var bucketExists = ossClient.DoesBucketExist(GetBucketName(args)); |
|||
|
|||
return Task.FromResult(bucketExists); |
|||
} |
|||
|
|||
private static string GetBucketName(BlobProviderArgs args) |
|||
{ |
|||
var configuration = args.Configuration.GetAliyunConfiguration(); |
|||
return configuration.BucketName.IsNullOrWhiteSpace() |
|||
? args.ContainerName |
|||
: configuration.BucketName; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,62 @@ |
|||
using System.Collections.Generic; |
|||
using Volo.Abp; |
|||
using Volo.Abp.BlobStoring; |
|||
|
|||
namespace LINGYUN.Abp.BlobStoring.Aliyun |
|||
{ |
|||
public class AliyunBlobProviderConfiguration |
|||
{ |
|||
/// <summary>
|
|||
/// 数据中心
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// 详见 https://help.aliyun.com/document_detail/31837.html?spm=a2c4g.11186623.2.14.417cd47eLc9LHc#concept-zt4-cvy-5db
|
|||
/// </remarks>
|
|||
public string Endpoint |
|||
{ |
|||
get => _containerConfiguration.GetConfiguration<string>(AliyunBlobProviderConfigurationNames.Endpoint); |
|||
set => _containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.Endpoint, Check.NotNullOrWhiteSpace(value, nameof(value))); |
|||
} |
|||
/// <summary>
|
|||
/// 命名空间
|
|||
/// </summary>
|
|||
public string BucketName |
|||
{ |
|||
get => _containerConfiguration.GetConfiguration<string>(AliyunBlobProviderConfigurationNames.BucketName); |
|||
set => _containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.BucketName, Check.NotNullOrWhiteSpace(value, nameof(value))); |
|||
} |
|||
/// <summary>
|
|||
/// 命名空间不存在是否创建
|
|||
/// </summary>
|
|||
public bool CreateBucketIfNotExists |
|||
{ |
|||
get => _containerConfiguration.GetConfigurationOrDefault(AliyunBlobProviderConfigurationNames.CreateBucketIfNotExists, false); |
|||
set => _containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.CreateBucketIfNotExists, value); |
|||
} |
|||
/// <summary>
|
|||
/// 创建命名空间时防盗链列表
|
|||
/// </summary>
|
|||
public List<string> CreateBucketReferer |
|||
{ |
|||
get => _containerConfiguration.GetConfiguration<List<string>>(AliyunBlobProviderConfigurationNames.CreateBucketReferer); |
|||
set |
|||
{ |
|||
if (value == null) |
|||
{ |
|||
_containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.CreateBucketReferer, new List<string>()); |
|||
} |
|||
else |
|||
{ |
|||
_containerConfiguration.SetConfiguration(AliyunBlobProviderConfigurationNames.CreateBucketReferer, value); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private readonly BlobContainerConfiguration _containerConfiguration; |
|||
|
|||
public AliyunBlobProviderConfiguration(BlobContainerConfiguration containerConfiguration) |
|||
{ |
|||
_containerConfiguration = containerConfiguration; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
namespace LINGYUN.Abp.BlobStoring.Aliyun |
|||
{ |
|||
public static class AliyunBlobProviderConfigurationNames |
|||
{ |
|||
/// <summary>
|
|||
/// 数据中心
|
|||
/// </summary>
|
|||
public const string Endpoint = "Aliyun:OSS:Endpoint"; |
|||
/// <summary>
|
|||
/// 命名空间
|
|||
/// </summary>
|
|||
public const string BucketName = "Aliyun:OSS:BucketName"; |
|||
/// <summary>
|
|||
/// 命名空间不存在是否创建
|
|||
/// </summary>
|
|||
public const string CreateBucketIfNotExists = "Aliyun:OSS:CreateBucketIfNotExists"; |
|||
/// <summary>
|
|||
/// 创建命名空间时防盗链列表
|
|||
/// </summary>
|
|||
public const string CreateBucketReferer = "Aliyun:OSS:CreateBucketReferer"; |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
using Volo.Abp.BlobStoring; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace LINGYUN.Abp.BlobStoring.Aliyun |
|||
{ |
|||
public class DefaultAliyunBlobNameCalculator : IAliyunBlobNameCalculator, ITransientDependency |
|||
{ |
|||
protected ICurrentTenant CurrentTenant { get; } |
|||
|
|||
public DefaultAliyunBlobNameCalculator( |
|||
ICurrentTenant currentTenant) |
|||
{ |
|||
CurrentTenant = currentTenant; |
|||
} |
|||
|
|||
public string Calculate(BlobProviderArgs args) |
|||
{ |
|||
return CurrentTenant.Id == null |
|||
? $"host/{args.BlobName}" |
|||
: $"tenants/{CurrentTenant.Id.Value:D}/{args.BlobName}"; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using Volo.Abp.BlobStoring; |
|||
|
|||
namespace LINGYUN.Abp.BlobStoring.Aliyun |
|||
{ |
|||
public interface IAliyunBlobNameCalculator |
|||
{ |
|||
string Calculate(BlobProviderArgs args); |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netcoreapp3.1</TargetFramework> |
|||
<RootNamespace /> |
|||
<IsPackable>false</IsPackable> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\modules\common\LINGYUN.Abp.BlobStoring.Aliyun\LINGYUN.Abp.BlobStoring.Aliyun.csproj" /> |
|||
<ProjectReference Include="..\LINGYUN.Abp.TestBase\LINGYUN.Abp.TestsBase.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,9 @@ |
|||
using LINGYUN.Abp.Tests; |
|||
|
|||
namespace LINGYUN.Abp.BlobStoring.Aliyun |
|||
{ |
|||
public class AbpBlobStoringAliyunTestBase : AbpTestsBase<AbpBlobStoringAliyunTestModule> |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,56 @@ |
|||
using Aliyun.OSS; |
|||
using LINGYUN.Abp.Tests; |
|||
using Microsoft.Extensions.Configuration; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using System; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Autofac; |
|||
using Volo.Abp.BlobStoring; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.BlobStoring.Aliyun |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpBlobStoringModule), |
|||
typeof(AbpBlobStoringAliyunModule), |
|||
typeof(AbpTestsBaseModule), |
|||
typeof(AbpAutofacModule) |
|||
)] |
|||
public class AbpBlobStoringAliyunTestModule : AbpModule |
|||
{ |
|||
private string _bucketName; |
|||
private string _accessKeyId; |
|||
private string _accessKeySecret; |
|||
private string _endPoint; |
|||
|
|||
public override void PreConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
var configurationOptions = new AbpConfigurationBuilderOptions |
|||
{ |
|||
BasePath = @"D:\Projects\Development\Abp\BlobStoring\Aliyun", |
|||
EnvironmentName = "Development" |
|||
}; |
|||
|
|||
context.Services.ReplaceConfiguration(ConfigurationHelper.BuildConfiguration(configurationOptions)); |
|||
} |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
var configuration = context.Services.GetConfiguration(); |
|||
|
|||
_endPoint = configuration[AliyunBlobProviderConfigurationNames.Endpoint]; |
|||
_bucketName = configuration[AliyunBlobProviderConfigurationNames.BucketName]; |
|||
_accessKeyId = configuration["Aliyun:Auth:AccessKeyId"]; |
|||
_accessKeySecret = configuration["Aliyun:Auth:AccessKeySecret"]; |
|||
} |
|||
|
|||
public override void OnApplicationShutdown(ApplicationShutdownContext context) |
|||
{ |
|||
var ossClient = new OssClient(_endPoint, _accessKeyId, _accessKeySecret); |
|||
if (ossClient.DoesBucketExist(_bucketName)) |
|||
{ |
|||
ossClient.DeleteBucket(_bucketName); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,99 @@ |
|||
using LINGYUN.Abp.BlobStoring.TestObjects; |
|||
using Shouldly; |
|||
using System; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.BlobStoring; |
|||
using Xunit; |
|||
|
|||
namespace LINGYUN.Abp.BlobStoring.Aliyun |
|||
{ |
|||
public class BlobContainer_Tests : AbpBlobStoringAliyunTestBase |
|||
{ |
|||
protected IBlobContainer<TestContainer1> Container { get; } |
|||
public BlobContainer_Tests() |
|||
{ |
|||
Container = GetRequiredService<IBlobContainer<TestContainer1>>(); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData("test-blob-1")] |
|||
[InlineData("test-blob-1.txt")] |
|||
[InlineData("test-folder/test-blob-1")] |
|||
public async Task Should_Save_And_Get_Blobs(string blobName) |
|||
{ |
|||
var testContent = "test content".GetBytes(); |
|||
await Container.SaveAsync(blobName, testContent); |
|||
try |
|||
{ |
|||
var resultBytes = await Container.GetAllBytesAsync(blobName); |
|||
resultBytes.SequenceEqual(testContent).ShouldBeTrue(); |
|||
} |
|||
finally |
|||
{ |
|||
await Container.DeleteAsync(blobName); |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public async Task Should_Overwrite_Pre_Saved_Blob_If_Requested() |
|||
{ |
|||
var blobName = "test-blob-1"; |
|||
|
|||
var testContent = "test content".GetBytes(); |
|||
await Container.SaveAsync(blobName, testContent); |
|||
|
|||
var testContentOverwritten = "test content overwritten".GetBytes(); |
|||
await Container.SaveAsync(blobName, testContentOverwritten, true); |
|||
|
|||
var result = await Container.GetAllBytesAsync(blobName); |
|||
result.SequenceEqual(testContentOverwritten).ShouldBeTrue(); |
|||
|
|||
await Container.DeleteAsync(blobName); |
|||
} |
|||
|
|||
|
|||
[Fact] |
|||
public async Task Should_Not_Allow_To_Overwrite_Pre_Saved_Blob_By_Default() |
|||
{ |
|||
var blobName = "test-blob-1"; |
|||
|
|||
var testContent = "test content".GetBytes(); |
|||
await Container.SaveAsync(blobName, testContent); |
|||
|
|||
var testContentOverwritten = "test content overwritten".GetBytes(); |
|||
await Assert.ThrowsAsync<BlobAlreadyExistsException>(() => |
|||
Container.SaveAsync(blobName, testContentOverwritten) |
|||
); |
|||
|
|||
await Container.DeleteAsync(blobName); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData("test-blob-1")] |
|||
[InlineData("test-blob-1.txt")] |
|||
[InlineData("test-folder/test-blob-1")] |
|||
public async Task Should_Delete_Saved_Blobs(string blobName) |
|||
{ |
|||
await Container.SaveAsync(blobName, "test content".GetBytes()); |
|||
(await Container.GetAllBytesAsync(blobName)).ShouldNotBeNull(); |
|||
|
|||
await Container.DeleteAsync(blobName); |
|||
(await Container.GetAllBytesOrNullAsync(blobName)).ShouldBeNull(); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData("test-blob-1")] |
|||
[InlineData("test-blob-1.txt")] |
|||
[InlineData("test-folder/test-blob-1")] |
|||
public virtual async Task Saved_Blobs_Should_Exists(string blobName) |
|||
{ |
|||
await Container.SaveAsync(blobName, "test content".GetBytes()); |
|||
(await Container.ExistsAsync(blobName)).ShouldBeTrue(); |
|||
|
|||
await Container.DeleteAsync(blobName); |
|||
(await Container.ExistsAsync(blobName)).ShouldBeFalse(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
namespace LINGYUN.Abp.BlobStoring.TestObjects |
|||
{ |
|||
public class TestContainer1 |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netcoreapp3.1</TargetFramework> |
|||
<RootNamespace /> |
|||
<IsPackable>false</IsPackable> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" /> |
|||
<PackageReference Include="NSubstitute" Version="4.2.1" /> |
|||
<PackageReference Include="Shouldly" Version="3.0.2" /> |
|||
<PackageReference Include="xunit" Version="2.4.1" /> |
|||
<PackageReference Include="xunit.extensibility.execution" Version="2.4.1" /> |
|||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" /> |
|||
<PackageReference Include="Volo.Abp.Autofac" Version="2.9.0" /> |
|||
<PackageReference Include="Volo.Abp.Authorization" Version="2.9.0" /> |
|||
<PackageReference Include="Volo.Abp.TestBase" Version="2.9.0" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,59 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.Testing; |
|||
using Volo.Abp.Uow; |
|||
|
|||
namespace LINGYUN.Abp.Tests |
|||
{ |
|||
public abstract class AbpTestsBase<TStartupModule> : AbpIntegratedTest<TStartupModule> |
|||
where TStartupModule : IAbpModule |
|||
{ |
|||
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) |
|||
{ |
|||
options.UseAutofac(); |
|||
} |
|||
|
|||
protected virtual Task WithUnitOfWorkAsync(Func<Task> func) |
|||
{ |
|||
return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); |
|||
} |
|||
|
|||
protected virtual async Task WithUnitOfWorkAsync(AbpUnitOfWorkOptions options, Func<Task> action) |
|||
{ |
|||
using (var scope = ServiceProvider.CreateScope()) |
|||
{ |
|||
var uowManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>(); |
|||
|
|||
using (var uow = uowManager.Begin(options)) |
|||
{ |
|||
await action(); |
|||
|
|||
await uow.CompleteAsync(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
protected virtual Task<TResult> WithUnitOfWorkAsync<TResult>(Func<Task<TResult>> func) |
|||
{ |
|||
return WithUnitOfWorkAsync(new AbpUnitOfWorkOptions(), func); |
|||
} |
|||
|
|||
protected virtual async Task<TResult> WithUnitOfWorkAsync<TResult>(AbpUnitOfWorkOptions options, Func<Task<TResult>> func) |
|||
{ |
|||
using (var scope = ServiceProvider.CreateScope()) |
|||
{ |
|||
var uowManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>(); |
|||
|
|||
using (var uow = uowManager.Begin(options)) |
|||
{ |
|||
var result = await func(); |
|||
await uow.CompleteAsync(); |
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Authorization; |
|||
using Volo.Abp.Autofac; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.Tests |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpAutofacModule), |
|||
typeof(AbpTestBaseModule), |
|||
typeof(AbpAuthorizationModule) |
|||
)] |
|||
public class AbpTestsBaseModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddAlwaysAllowAuthorization(); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue