Browse Source

Implement azure blob storage.

pull/4200/head
maliming 6 years ago
parent
commit
44521a6bd3
  1. 7
      framework/Volo.Abp.sln
  2. 1
      framework/src/Volo.Abp.BlobStoring.Azure/Volo.Abp.BlobStoring.Azure.csproj
  3. 59
      framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs
  4. 12
      framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs
  5. 6
      framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfigurationNames.cs
  6. 2
      framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderArgs.cs
  7. 3
      framework/src/Volo.Abp.Core/System/IO/AbpStreamExtensions.cs
  8. 19
      framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo.Abp.BlobStoring.Azure.Tests.csproj
  9. 12
      framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestBase.cs
  10. 49
      framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs
  11. 12
      framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AzureBlobContainer_Tests.cs

7
framework/Volo.Abp.sln

@ -303,6 +303,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.EntityFrameworkCor
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BlobStoring.Azure", "src\Volo.Abp.BlobStoring.Azure\Volo.Abp.BlobStoring.Azure.csproj", "{C44242F7-D55D-4867-AAF4-A786E404312E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BlobStoring.Azure.Tests", "test\Volo.Abp.BlobStoring.Azure.Tests\Volo.Abp.BlobStoring.Azure.Tests.csproj", "{A80E9A0B-8932-4B5D-83FB-6751708FD484}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -901,6 +903,10 @@ Global
{C44242F7-D55D-4867-AAF4-A786E404312E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C44242F7-D55D-4867-AAF4-A786E404312E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C44242F7-D55D-4867-AAF4-A786E404312E}.Release|Any CPU.Build.0 = Release|Any CPU
{A80E9A0B-8932-4B5D-83FB-6751708FD484}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A80E9A0B-8932-4B5D-83FB-6751708FD484}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A80E9A0B-8932-4B5D-83FB-6751708FD484}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A80E9A0B-8932-4B5D-83FB-6751708FD484}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -1054,6 +1060,7 @@ Global
{68443D4A-1608-4039-B995-7AF4CF82E9F8} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{75E5C841-5F36-4C44-A532-57CB8E7FFE15} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{C44242F7-D55D-4867-AAF4-A786E404312E} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{A80E9A0B-8932-4B5D-83FB-6751708FD484} = {447C8A77-E5F0-4538-8687-7383196D04EA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

1
framework/src/Volo.Abp.BlobStoring.Azure/Volo.Abp.BlobStoring.Azure.csproj

@ -16,6 +16,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.BlobStoring\Volo.Abp.BlobStoring.csproj" />
<PackageReference Include="Azure.Storage.Blobs" Version="12.4.3" />
</ItemGroup>
</Project>

59
framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProvider.cs

@ -1,29 +1,72 @@
using System.IO;
using System.Threading.Tasks;
using Azure.Storage.Blobs;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.BlobStoring.Azure
{
public class AzureBlobProvider : BlobProviderBase, ITransientDependency
{
public override Task SaveAsync(BlobProviderSaveArgs args)
public override async Task SaveAsync(BlobProviderSaveArgs args)
{
throw new System.NotImplementedException();
var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), args.BlobName);
if (!args.OverrideExisting && await BlobExistsAsync(blobClient))
{
throw new BlobAlreadyExistsException($"Saving BLOB '{args.BlobName}' does already exists in the container '{args.ContainerName}'! Set {nameof(args.OverrideExisting)} if it should be overwritten.");
}
await blobClient.UploadAsync(args.BlobStream, true);
}
public override async Task<bool> DeleteAsync(BlobProviderDeleteArgs args)
{
var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), args.BlobName);
if (await BlobExistsAsync(blobClient))
{
return (await blobClient.DeleteAsync()).Status == 200;
}
return false;
}
public override async Task<bool> ExistsAsync(BlobProviderExistsArgs args)
{
var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), args.BlobName);
return await BlobExistsAsync(blobClient);
}
public override async Task<Stream> GetOrNullAsync(BlobProviderGetArgs args)
{
var blobClient = GetBlobClient(args.Configuration.GetAzureConfiguration(), args.BlobName);
if (!await BlobExistsAsync(blobClient))
{
return null;
}
var download = await blobClient.DownloadAsync();
var memoryStream = new MemoryStream();
await download.Value.Content.CopyToAsync(memoryStream);
return memoryStream;
}
public override Task<bool> DeleteAsync(BlobProviderDeleteArgs args)
protected virtual BlobClient GetBlobClient(AzureBlobProviderConfiguration configuration, string blobName)
{
throw new System.NotImplementedException();
var blobContainerClient = GetBlobContainerClient(configuration);
return blobContainerClient.GetBlobClient(blobName);
}
public override Task<bool> ExistsAsync(BlobProviderExistsArgs args)
protected virtual BlobContainerClient GetBlobContainerClient(AzureBlobProviderConfiguration configuration)
{
throw new System.NotImplementedException();
var blobServiceClient = new BlobServiceClient(configuration.ConnectionString);
return blobServiceClient.GetBlobContainerClient(configuration.ContainerName);
}
public override Task<Stream> GetOrNullAsync(BlobProviderGetArgs args)
private static async Task<bool> BlobExistsAsync(BlobClient blobClient)
{
throw new System.NotImplementedException();
var response = await blobClient.ExistsAsync();
return response.Value;
}
}
}

12
framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfiguration.cs

@ -2,6 +2,18 @@
{
public class AzureBlobProviderConfiguration
{
public string ConnectionString
{
get => _containerConfiguration.GetConfiguration<string>(AzureBlobProviderConfigurationNames.ConnectionString);
set => _containerConfiguration.SetConfiguration(AzureBlobProviderConfigurationNames.ConnectionString, Check.NotNullOrWhiteSpace(value, nameof(value)));
}
public string ContainerName
{
get => _containerConfiguration.GetConfiguration<string>(AzureBlobProviderConfigurationNames.ContainerName);
set => _containerConfiguration.SetConfiguration(AzureBlobProviderConfigurationNames.ContainerName, Check.NotNullOrWhiteSpace(value, nameof(value)));
}
private readonly BlobContainerConfiguration _containerConfiguration;
public AzureBlobProviderConfiguration(BlobContainerConfiguration containerConfiguration)

6
framework/src/Volo.Abp.BlobStoring.Azure/Volo/Abp/BlobStoring/Azure/AzureBlobProviderConfigurationNames.cs

@ -1,8 +1,8 @@
namespace Volo.Abp.BlobStoring.Azure
{
public class AzureBlobProviderConfigurationNames
public static class AzureBlobProviderConfigurationNames
{
public const string ConnectionString = "Azure.ConnectionString";
public const string ContainerName = "Azure.ContainerName";
}
}

2
framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobProviderArgs.cs

@ -28,4 +28,4 @@ namespace Volo.Abp.BlobStoring
CancellationToken = cancellationToken;
}
}
}
}

3
framework/src/Volo.Abp.Core/System/IO/AbpStreamExtensions.cs

@ -9,6 +9,7 @@ namespace System.IO
{
using (var memoryStream = new MemoryStream())
{
stream.Position = 0;
stream.CopyTo(memoryStream);
return memoryStream.ToArray();
}
@ -18,6 +19,7 @@ namespace System.IO
{
using (var memoryStream = new MemoryStream())
{
stream.Position = 0;
await stream.CopyToAsync(memoryStream, cancellationToken);
return memoryStream.ToArray();
}
@ -25,6 +27,7 @@ namespace System.IO
public static Task CopyToAsync(this Stream stream, Stream destination, CancellationToken cancellationToken)
{
stream.Position = 0;
return stream.CopyToAsync(
destination,
81920, //this is already the default value, but needed to set to be able to pass the cancellationToken

19
framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo.Abp.BlobStoring.Azure.Tests.csproj

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.test.props" />
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace />
<UserSecretsId>9f0d2c00-80c1-435b-bfab-2c39c8249091</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.BlobStoring.Azure\Volo.Abp.BlobStoring.Azure.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
<ProjectReference Include="..\Volo.Abp.BlobStoring.Tests\Volo.Abp.BlobStoring.Tests.csproj" />
</ItemGroup>
</Project>

12
framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestBase.cs

@ -0,0 +1,12 @@
using Volo.Abp.Testing;
namespace Volo.Abp.BlobStoring.Azure
{
public class AbpBlobStoringAzureTestBase : AbpIntegratedTest<AbpBlobStoringAzureTestModule>
{
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
options.UseAutofac();
}
}
}

49
framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AbpBlobStoringAzureTestModule.cs

@ -0,0 +1,49 @@
using System;
using Azure.Storage.Blobs;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
namespace Volo.Abp.BlobStoring.Azure
{
[DependsOn(
typeof(AbpBlobStoringAzureModule),
typeof(AbpBlobStoringTestModule)
)]
public class AbpBlobStoringAzureTestModule : AbpModule
{
private readonly string _randomContainerName = "abp-azure-test-container-" + Guid.NewGuid().ToString("N");
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.ReplaceConfiguration(ConfigurationHelper.BuildConfiguration(builderAction: builder =>
{
builder.AddUserSecrets("9f0d2c00-80c1-435b-bfab-2c39c8249091");
}));
var configuration = context.Services.GetConfiguration();
var blobServiceClient = new BlobServiceClient(configuration["Azure:ConnectionString"]);
blobServiceClient.CreateBlobContainer(_randomContainerName);
Configure<AbpBlobStoringOptions>(options =>
{
options.Containers.ConfigureAll((containerName, containerConfiguration) =>
{
containerConfiguration.UseAzure(azure =>
{
azure.ConnectionString = configuration["Azure:ConnectionString"];
azure.ContainerName = _randomContainerName;
});
});
});
}
public override void OnApplicationShutdown(ApplicationShutdownContext context)
{
var configuration = context.ServiceProvider.GetRequiredService<IConfiguration>();
var blobServiceClient = new BlobServiceClient(configuration["Azure:ConnectionString"]);
blobServiceClient.DeleteBlobContainer(_randomContainerName);
}
}
}

12
framework/test/Volo.Abp.BlobStoring.Azure.Tests/Volo/Abp/BlobStoring/Azure/AzureBlobContainer_Tests.cs

@ -0,0 +1,12 @@
using Xunit;
namespace Volo.Abp.BlobStoring.Azure
{
public class AzureBlobContainer_Tests : BlobContainer_Tests<AbpBlobStoringAzureTestModule>
{
public AzureBlobContainer_Tests()
{
}
}
}
Loading…
Cancel
Save