mirror of https://github.com/abpframework/abp.git
15 changed files with 244 additions and 4 deletions
@ -0,0 +1,35 @@ |
|||||
|
# BLOB Storing Memory Provider |
||||
|
|
||||
|
Memory Storage Provider is used to store BLOBs in the memory. This is mainly used for unit testing purposes. |
||||
|
|
||||
|
> Read the [BLOB Storing document](../blob-storing) to understand how to use the BLOB storing system. This document only covers how to configure containers to use the memory. |
||||
|
|
||||
|
## Installation |
||||
|
|
||||
|
Use the ABP CLI to add [Volo.Abp.BlobStoring.Memory](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Memory) NuGet package to your project: |
||||
|
|
||||
|
* Install the [ABP CLI](../../../cli) if you haven't installed before. |
||||
|
* Open a command line (terminal) in the directory of the `.csproj` file you want to add the `Volo.Abp.BlobStoring.Memory` package. |
||||
|
* Run `abp add-package Volo.Abp.BlobStoring.Memory` command. |
||||
|
|
||||
|
If you want to do it manually, install the [Volo.Abp.BlobStoring.Memory](https://www.nuget.org/packages/Volo.Abp.BlobStoring.Memory) NuGet package to your project and add `[DependsOn(typeof(AbpBlobStoringMemoryModule))]` to the [ABP module](../../architecture/modularity/basics.md) class inside your project. |
||||
|
|
||||
|
## Configuration |
||||
|
|
||||
|
Configuration is done in the `ConfigureServices` method of your [module](../../architecture/modularity/basics.md) class, as explained in the [BLOB Storing document](../blob-storing). |
||||
|
|
||||
|
**Example: Configure to use the Memory storage provider by default** |
||||
|
|
||||
|
````csharp |
||||
|
Configure<AbpBlobStoringOptions>(options => |
||||
|
{ |
||||
|
options.Containers.ConfigureDefault(container => |
||||
|
{ |
||||
|
container.UseMemory(); |
||||
|
}); |
||||
|
}); |
||||
|
```` |
||||
|
|
||||
|
`UseMemory` extension method is used to set the Memory Provider for a container. |
||||
|
|
||||
|
> See the [BLOB Storing document](../blob-storing) to learn how to configure this provider for a specific container. |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</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,23 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0;net9.0;net10.0</TargetFrameworks> |
||||
|
<Nullable>enable</Nullable> |
||||
|
<WarningsAsErrors>Nullable</WarningsAsErrors> |
||||
|
<AssemblyName>Volo.Abp.BlobStoring.Memory</AssemblyName> |
||||
|
<PackageId>Volo.Abp.BlobStoring.Memory</PackageId> |
||||
|
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\Volo.Abp.BlobStoring\Volo.Abp.BlobStoring.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,9 @@ |
|||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace Volo.Abp.BlobStoring.Memory; |
||||
|
|
||||
|
[DependsOn(typeof(AbpBlobStoringModule))] |
||||
|
public class AbpBlobStoringMemoryModule : AbpModule |
||||
|
{ |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
namespace Volo.Abp.BlobStoring.Memory; |
||||
|
|
||||
|
public static class MemoryBlobContainerConfigurationExtensions |
||||
|
{ |
||||
|
public static BlobContainerConfiguration UseMemory(this BlobContainerConfiguration containerConfiguration) |
||||
|
{ |
||||
|
containerConfiguration.ProviderType = typeof(MemoryBlobProvider); |
||||
|
return containerConfiguration; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,65 @@ |
|||||
|
using System.Collections.Concurrent; |
||||
|
using System.IO; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace Volo.Abp.BlobStoring.Memory; |
||||
|
|
||||
|
public class MemoryBlobProvider : BlobProviderBase, ITransientDependency |
||||
|
{ |
||||
|
protected ConcurrentDictionary<string, byte[]> MemoryStore { get; } |
||||
|
|
||||
|
protected ICurrentTenant CurrentTenant { get; } |
||||
|
|
||||
|
public MemoryBlobProvider(ICurrentTenant currentTenant) |
||||
|
{ |
||||
|
MemoryStore = new ConcurrentDictionary<string, byte[]>(); |
||||
|
|
||||
|
CurrentTenant = currentTenant; |
||||
|
} |
||||
|
|
||||
|
public override async Task SaveAsync(BlobProviderSaveArgs args) |
||||
|
{ |
||||
|
var cacheKey = GetCacheKey(args); |
||||
|
|
||||
|
using var buffer = new MemoryStream(); |
||||
|
await args.BlobStream.CopyToAsync(buffer); |
||||
|
var bytes = buffer.ToArray(); |
||||
|
|
||||
|
if (!args.OverrideExisting) |
||||
|
{ |
||||
|
if (!MemoryStore.TryAdd(cacheKey, bytes)) |
||||
|
{ |
||||
|
throw new BlobAlreadyExistsException( |
||||
|
$"Saving BLOB '{args.BlobName}' does already exists in the container '{args.ContainerName}'! Set {nameof(args.OverrideExisting)} if it should be overwritten."); |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
MemoryStore.AddOrUpdate(cacheKey, bytes, (_, __) => bytes); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override Task<bool> DeleteAsync(BlobProviderDeleteArgs args) |
||||
|
{ |
||||
|
return Task.FromResult(MemoryStore.TryRemove(GetCacheKey(args), out _)); |
||||
|
} |
||||
|
|
||||
|
public override Task<bool> ExistsAsync(BlobProviderExistsArgs args) |
||||
|
{ |
||||
|
return Task.FromResult(MemoryStore.ContainsKey(GetCacheKey(args))); |
||||
|
} |
||||
|
|
||||
|
public override Task<Stream?> GetOrNullAsync(BlobProviderGetArgs args) |
||||
|
{ |
||||
|
return MemoryStore.TryGetValue(GetCacheKey(args), out var bytes) |
||||
|
? Task.FromResult<Stream?>(new MemoryStream(bytes, writable: false)) |
||||
|
: Task.FromResult<Stream?>(null); |
||||
|
} |
||||
|
|
||||
|
protected virtual string GetCacheKey(BlobProviderArgs args) |
||||
|
{ |
||||
|
return $"{CurrentTenant.Id}_{args.BlobName}_{args.ContainerName}"; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\common.test.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net10.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\src\Volo.Abp.BlobStoring.Memory\Volo.Abp.BlobStoring.Memory.csproj" /> |
||||
|
<ProjectReference Include="..\..\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" /> |
||||
|
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" /> |
||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" /> |
||||
|
<ProjectReference Include="..\Volo.Abp.BlobStoring.Tests\Volo.Abp.BlobStoring.Tests.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,21 @@ |
|||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace Volo.Abp.BlobStoring.Memory; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpBlobStoringMemoryModule), |
||||
|
typeof(AbpBlobStoringTestModule) |
||||
|
)] |
||||
|
public class AbpBlobStoringMemoryTestModule : AbpModule |
||||
|
{ |
||||
|
public override void PostConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpBlobStoringOptions>(options => |
||||
|
{ |
||||
|
options.Containers.ConfigureAll((containerName, containerConfiguration) => |
||||
|
{ |
||||
|
containerConfiguration.UseMemory(); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,6 @@ |
|||||
|
namespace Volo.Abp.BlobStoring.Memory; |
||||
|
|
||||
|
public class MemoryBlobContainer_Tests : BlobContainer_Tests<AbpBlobStoringMemoryTestModule> |
||||
|
{ |
||||
|
|
||||
|
} |
||||
@ -1,14 +1,26 @@ |
|||||
using Volo.Abp.Modularity; |
using Volo.Abp.BlobStoring; |
||||
|
using Volo.Abp.BlobStoring.Memory; |
||||
|
using Volo.Abp.Modularity; |
||||
using Volo.Docs.Admin; |
using Volo.Docs.Admin; |
||||
|
|
||||
namespace Volo.Docs |
namespace Volo.Docs |
||||
{ |
{ |
||||
[DependsOn( |
[DependsOn( |
||||
typeof(DocsAdminApplicationModule), |
typeof(DocsAdminApplicationModule), |
||||
typeof(DocsDomainTestModule) |
typeof(DocsDomainTestModule), |
||||
|
typeof(AbpBlobStoringMemoryModule) |
||||
)] |
)] |
||||
public class DocsAdminApplicationTestModule : AbpModule |
public class DocsAdminApplicationTestModule : AbpModule |
||||
{ |
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpBlobStoringOptions>(options => |
||||
|
{ |
||||
|
options.Containers.ConfigureDefault(container => |
||||
|
{ |
||||
|
container.UseMemory(); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
Loading…
Reference in new issue