mirror of https://github.com/Squidex/squidex.git
7 changed files with 242 additions and 2 deletions
@ -0,0 +1,29 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using Microsoft.Extensions.Configuration; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Squidex.Infrastructure.Assets; |
||||
|
using Squidex.Infrastructure.Plugins; |
||||
|
|
||||
|
namespace Squidex.Extensions.Samples |
||||
|
{ |
||||
|
public sealed class MemoryAssetStorePlugin : IPlugin |
||||
|
{ |
||||
|
public void ConfigureServices(IServiceCollection services, IConfiguration configuration) |
||||
|
{ |
||||
|
var storeType = configuration.GetValue<string>("assetStore:type"); |
||||
|
|
||||
|
if (string.Equals(storeType, "Memory", StringComparison.OrdinalIgnoreCase)) |
||||
|
{ |
||||
|
services.AddSingletonAs<MemoryAssetStore>() |
||||
|
.As<IAssetStore>(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,119 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Collections.Concurrent; |
||||
|
using System.IO; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Squidex.Infrastructure.Tasks; |
||||
|
|
||||
|
namespace Squidex.Infrastructure.Assets |
||||
|
{ |
||||
|
public sealed class MemoryAssetStore : IAssetStore |
||||
|
{ |
||||
|
private readonly ConcurrentDictionary<string, MemoryStream> streams = new ConcurrentDictionary<string, MemoryStream>(); |
||||
|
private readonly AsyncLock readerLock = new AsyncLock(); |
||||
|
private readonly AsyncLock writerLock = new AsyncLock(); |
||||
|
|
||||
|
public string GeneratePublicUrl(string id, long version, string suffix) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public async Task CopyAsync(string sourceFileName, string id, long version, string suffix, CancellationToken ct = default) |
||||
|
{ |
||||
|
Guard.NotNullOrEmpty(sourceFileName, nameof(sourceFileName)); |
||||
|
Guard.NotNullOrEmpty(id, nameof(id)); |
||||
|
|
||||
|
if (!streams.TryGetValue(sourceFileName, out var sourceStream)) |
||||
|
{ |
||||
|
throw new AssetNotFoundException(sourceFileName); |
||||
|
} |
||||
|
|
||||
|
using (await readerLock.LockAsync()) |
||||
|
{ |
||||
|
await UploadAsync(id, version, suffix, sourceStream, ct); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public async Task DownloadAsync(string id, long version, string suffix, Stream stream, CancellationToken ct = default) |
||||
|
{ |
||||
|
Guard.NotNullOrEmpty(id, nameof(id)); |
||||
|
|
||||
|
var fileName = GetFileName(id, version, suffix); |
||||
|
|
||||
|
if (!streams.TryGetValue(fileName, out var sourceStream)) |
||||
|
{ |
||||
|
throw new AssetNotFoundException(fileName); |
||||
|
} |
||||
|
|
||||
|
using (await readerLock.LockAsync()) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
await sourceStream.CopyToAsync(stream, 81920, ct); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
sourceStream.Position = 0; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public Task UploadAsync(string id, long version, string suffix, Stream stream, CancellationToken ct = default) |
||||
|
{ |
||||
|
Guard.NotNullOrEmpty(id, nameof(id)); |
||||
|
|
||||
|
return UploadAsync(GetFileName(id, version, suffix), stream, ct); |
||||
|
} |
||||
|
|
||||
|
public async Task UploadAsync(string fileName, Stream stream, CancellationToken ct = default) |
||||
|
{ |
||||
|
var memoryStream = new MemoryStream(); |
||||
|
|
||||
|
if (streams.TryAdd(fileName, memoryStream)) |
||||
|
{ |
||||
|
using (await writerLock.LockAsync()) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
await stream.CopyToAsync(memoryStream, 81920, ct); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
memoryStream.Position = 0; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
throw new AssetAlreadyExistsException(fileName); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public Task DeleteAsync(string id, long version, string suffix) |
||||
|
{ |
||||
|
Guard.NotNullOrEmpty(id, nameof(id)); |
||||
|
|
||||
|
return DeleteAsync(GetFileName(id, version, suffix)); |
||||
|
} |
||||
|
|
||||
|
public Task DeleteAsync(string fileName) |
||||
|
{ |
||||
|
Guard.NotNullOrEmpty(fileName, nameof(fileName)); |
||||
|
|
||||
|
streams.TryRemove(fileName, out _); |
||||
|
|
||||
|
return TaskHelper.Done; |
||||
|
} |
||||
|
|
||||
|
private string GetFileName(string id, long version, string suffix) |
||||
|
{ |
||||
|
return StringExtensions.JoinNonEmpty("_", id, version.ToString(), suffix); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,52 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System; |
||||
|
using System.IO; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace Squidex.Infrastructure.Assets |
||||
|
{ |
||||
|
public sealed class NoopAssetStore : IAssetStore |
||||
|
{ |
||||
|
public string GeneratePublicUrl(string id, long version, string suffix) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public Task CopyAsync(string sourceFileName, string id, long version, string suffix, CancellationToken ct = default) |
||||
|
{ |
||||
|
throw new NotSupportedException(); |
||||
|
} |
||||
|
|
||||
|
public Task DownloadAsync(string id, long version, string suffix, Stream stream, CancellationToken ct = default) |
||||
|
{ |
||||
|
throw new NotSupportedException(); |
||||
|
} |
||||
|
|
||||
|
public Task UploadAsync(string fileName, Stream stream, CancellationToken ct = default) |
||||
|
{ |
||||
|
throw new NotSupportedException(); |
||||
|
} |
||||
|
|
||||
|
public Task UploadAsync(string id, long version, string suffix, Stream stream, CancellationToken ct = default) |
||||
|
{ |
||||
|
throw new NotSupportedException(); |
||||
|
} |
||||
|
|
||||
|
public Task DeleteAsync(string fileName) |
||||
|
{ |
||||
|
throw new NotSupportedException(); |
||||
|
} |
||||
|
|
||||
|
public Task DeleteAsync(string id, long version, string suffix) |
||||
|
{ |
||||
|
throw new NotSupportedException(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,31 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Squidex.Infrastructure.Assets |
||||
|
{ |
||||
|
public class MemoryAssetStoreTests : AssetStoreTests<MemoryAssetStore> |
||||
|
{ |
||||
|
public override MemoryAssetStore CreateStore() |
||||
|
{ |
||||
|
return new MemoryAssetStore(); |
||||
|
} |
||||
|
|
||||
|
public override void Dispose() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Should_not_calculate_source_url() |
||||
|
{ |
||||
|
var url = Sut.GeneratePublicUrl(AssetId, 1, null); |
||||
|
|
||||
|
Assert.Null(url); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue