diff --git a/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs b/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs index a06c2c1018..9194a78652 100644 --- a/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs +++ b/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo/Abp/BlobStoring/FileSystem/FileSystemBlobProvider.cs @@ -33,7 +33,6 @@ namespace Volo.Abp.BlobStoring.FileSystem await args.BlobStream.CopyToAsync( fileStream, - 81920, //this is already the default value, but needed to set to be able to pass the cancellationToken args.CancellationToken ); diff --git a/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerExtensions.cs b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerExtensions.cs new file mode 100644 index 0000000000..58ae4ac593 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobContainerExtensions.cs @@ -0,0 +1,57 @@ +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace Volo.Abp.BlobStoring +{ + public static class BlobContainerExtensions + { + public static async Task SaveAsync( + this IBlobContainer container, + string name, + byte[] bytes, + bool overrideExisting = false, + CancellationToken cancellationToken = default + ) + { + using (var memoryStream = new MemoryStream(bytes)) + { + await container.SaveAsync( + name, + memoryStream, + overrideExisting, + cancellationToken + ); + } + } + + public static async Task GetAllBytesAsync( + this IBlobContainer container, + string name, + CancellationToken cancellationToken = default) + { + using (var stream = await container.GetAsync(name, cancellationToken)) + { + return await stream.GetAllBytesAsync(cancellationToken); + } + } + + public static async Task GetAllBytesOrNullAsync( + this IBlobContainer container, + string name, + CancellationToken cancellationToken = default) + { + var stream = await container.GetOrNullAsync(name, cancellationToken); + if (stream == null) + { + return null; + } + + using (stream) + { + return await stream.GetAllBytesAsync(cancellationToken); + } + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Core/System/IO/AbpStreamExtensions.cs b/framework/src/Volo.Abp.Core/System/IO/AbpStreamExtensions.cs index e87ab67527..466d73b2a7 100644 --- a/framework/src/Volo.Abp.Core/System/IO/AbpStreamExtensions.cs +++ b/framework/src/Volo.Abp.Core/System/IO/AbpStreamExtensions.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Threading; +using System.Threading.Tasks; namespace System.IO { @@ -13,13 +14,22 @@ namespace System.IO } } - public static async Task GetAllBytesAsync(this Stream stream) + public static async Task GetAllBytesAsync(this Stream stream, CancellationToken cancellationToken = default) { using (var memoryStream = new MemoryStream()) { - await stream.CopyToAsync(memoryStream); + await stream.CopyToAsync(memoryStream, cancellationToken); return memoryStream.ToArray(); } } + + public static Task CopyToAsync(this Stream stream, Stream destination, CancellationToken cancellationToken) + { + return stream.CopyToAsync( + destination, + 81920, //this is already the default value, but needed to set to be able to pass the cancellationToken + cancellationToken + ); + } } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/AbpException.cs b/framework/src/Volo.Abp.Core/Volo/Abp/AbpException.cs index 39792ecf34..ccc4a57dbe 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/AbpException.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/AbpException.cs @@ -8,38 +8,23 @@ namespace Volo.Abp /// public class AbpException : Exception { - /// - /// Creates a new object. - /// public AbpException() { } - /// - /// Creates a new object. - /// - /// Exception message public AbpException(string message) : base(message) { } - /// - /// Creates a new object. - /// - /// Exception message - /// Inner exception public AbpException(string message, Exception innerException) : base(message, innerException) { } - /// - /// Constructor for serializing. - /// public AbpException(SerializationInfo serializationInfo, StreamingContext context) : base(serializationInfo, context) { diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/AbpInitializationException.cs b/framework/src/Volo.Abp.Core/Volo/Abp/AbpInitializationException.cs index 1bcd513168..31d93d69bd 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/AbpInitializationException.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/AbpInitializationException.cs @@ -5,38 +5,23 @@ namespace Volo.Abp { public class AbpInitializationException : AbpException { - /// - /// Creates a new object. - /// public AbpInitializationException() { } - /// - /// Creates a new object. - /// - /// Exception message public AbpInitializationException(string message) : base(message) { } - /// - /// Creates a new object. - /// - /// Exception message - /// Inner exception public AbpInitializationException(string message, Exception innerException) : base(message, innerException) { } - /// - /// Constructor for serializing. - /// public AbpInitializationException(SerializationInfo serializationInfo, StreamingContext context) : base(serializationInfo, context) { diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/AbpShutdownException.cs b/framework/src/Volo.Abp.Core/Volo/Abp/AbpShutdownException.cs new file mode 100644 index 0000000000..1261c4f8b3 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/AbpShutdownException.cs @@ -0,0 +1,31 @@ +using System; +using System.Runtime.Serialization; + +namespace Volo.Abp +{ + public class AbpShutdownException : AbpException + { + public AbpShutdownException() + { + + } + + public AbpShutdownException(string message) + : base(message) + { + + } + + public AbpShutdownException(string message, Exception innerException) + : base(message, innerException) + { + + } + + public AbpShutdownException(SerializationInfo serializationInfo, StreamingContext context) + : base(serializationInfo, context) + { + + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/IO/DirectoryHelper.cs b/framework/src/Volo.Abp.Core/Volo/Abp/IO/DirectoryHelper.cs index 23f8de610a..661ba76b52 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/IO/DirectoryHelper.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/IO/DirectoryHelper.cs @@ -16,7 +16,23 @@ namespace Volo.Abp.IO Directory.CreateDirectory(directory); } } - + + public static void DeleteIfExists(string directory) + { + if (Directory.Exists(directory)) + { + Directory.Delete(directory); + } + } + + public static void DeleteIfExists(string directory, bool recursive) + { + if (Directory.Exists(directory)) + { + Directory.Delete(directory, recursive); + } + } + public static void CreateIfNotExists(DirectoryInfo directory) { if (!directory.Exists) @@ -36,7 +52,8 @@ namespace Volo.Abp.IO ); } - public static bool IsSubDirectoryOf([NotNull] DirectoryInfo parentDirectory, [NotNull] DirectoryInfo childDirectory) + public static bool IsSubDirectoryOf([NotNull] DirectoryInfo parentDirectory, + [NotNull] DirectoryInfo childDirectory) { Check.NotNull(parentDirectory, nameof(parentDirectory)); Check.NotNull(childDirectory, nameof(childDirectory)); @@ -66,10 +83,7 @@ namespace Volo.Abp.IO Directory.SetCurrentDirectory(targetDirectory); - return new DisposeAction(() => - { - Directory.SetCurrentDirectory(currentDirectory); - }); + return new DisposeAction(() => { Directory.SetCurrentDirectory(currentDirectory); }); } } -} +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ModuleManager.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ModuleManager.cs index e594a24603..70b9036150 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ModuleManager.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Modularity/ModuleManager.cs @@ -44,7 +44,7 @@ namespace Volo.Abp.Modularity } catch (Exception ex) { - throw new AbpInitializationException($"An error occurred during the initialize {contributor.GetType().FullName} phase of the module {module.Type.AssemblyQualifiedName}. See the inner exception for details.", ex); + throw new AbpInitializationException($"An error occurred during the initialize {contributor.GetType().FullName} phase of the module {module.Type.AssemblyQualifiedName}: {ex.Message}. See the inner exception for details.", ex); } } } @@ -76,7 +76,7 @@ namespace Volo.Abp.Modularity } catch (Exception ex) { - throw new AbpInitializationException($"An error occurred during the shutdown {contributor.GetType().FullName} phase of the module {module.Type.AssemblyQualifiedName}. See the inner exception for details.", ex); + throw new AbpShutdownException($"An error occurred during the shutdown {contributor.GetType().FullName} phase of the module {module.Type.AssemblyQualifiedName}: {ex.Message}. See the inner exception for details.", ex); } } } diff --git a/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/AbpBlobStoringFileSystemTestModule.cs b/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/AbpBlobStoringFileSystemTestModule.cs index a2ab6052bd..a18f8e40af 100644 --- a/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/AbpBlobStoringFileSystemTestModule.cs +++ b/framework/test/Volo.Abp.BlobStoring.FileSystem.Tests/Volo/Abp/BlobStoring/FileSystem/AbpBlobStoringFileSystemTestModule.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using Volo.Abp.IO; using Volo.Abp.Modularity; namespace Volo.Abp.BlobStoring.FileSystem @@ -10,6 +11,16 @@ namespace Volo.Abp.BlobStoring.FileSystem )] public class AbpBlobStoringFileSystemTestModule : AbpModule { + private readonly string _testDirectoryPath; + + public AbpBlobStoringFileSystemTestModule() + { + _testDirectoryPath = Path.Combine( + Path.GetTempPath(), + Guid.NewGuid().ToString("N") + ); + } + public override void ConfigureServices(ServiceConfigurationContext context) { Configure(options => @@ -18,10 +29,15 @@ namespace Volo.Abp.BlobStoring.FileSystem { containerConfiguration.UseFileSystem(fileSystem => { - fileSystem.BasePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); + fileSystem.BasePath = _testDirectoryPath; }); }); }); } + + public override void OnApplicationShutdown(ApplicationShutdownContext context) + { + DirectoryHelper.DeleteIfExists(_testDirectoryPath, true); + } } } \ No newline at end of file diff --git a/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/BlobContainer_Tests.cs b/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/BlobContainer_Tests.cs index 195e51f335..b995e18785 100644 --- a/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/BlobContainer_Tests.cs +++ b/framework/test/Volo.Abp.BlobStoring.Tests/Volo/Abp/BlobStoring/BlobContainer_Tests.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using System.Linq; using System.Threading.Tasks; using Shouldly; @@ -25,21 +24,53 @@ namespace Volo.Abp.BlobStoring options.UseAutofac(); } - [Fact] - public async Task SaveAsync() + [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(); - - using (var memoryStream = new MemoryStream(testContent)) - { - await Container.SaveAsync("test-blob-1", memoryStream); - } + await Container.SaveAsync(blobName, testContent); - using (var stream = await Container.GetAsync("test-blob-1")) - { - var result = await stream.GetAllBytesAsync(); - result.SequenceEqual(testContent).ShouldBeTrue(); - } + var result = await Container.GetAllBytesAsync(blobName); + result.SequenceEqual(testContent).ShouldBeTrue(); + } + + [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 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(); + } + + [Theory] + [InlineData("test-blob-1")] + [InlineData("test-blob-1.txt")] + [InlineData("test-folder/test-blob-1")] + public async Task Unknown_Blobs_Should_Not_Exists(string blobName) + { + await Container.DeleteAsync(blobName); + (await Container.ExistsAsync(blobName)).ShouldBeFalse(); } } } \ No newline at end of file