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 9194a78652..34be8c3eb3 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 @@ -6,7 +6,7 @@ using Volo.Abp.IO; namespace Volo.Abp.BlobStoring.FileSystem { //TODO: What if the file is being used on create, delete or read? - //TODO: Implement all methods truly async! + //TODO: Implement all methods truly async (if possible)! public class FileSystemBlobProvider : BlobProviderBase, ITransientDependency { @@ -20,6 +20,11 @@ namespace Volo.Abp.BlobStoring.FileSystem public override async Task SaveAsync(BlobProviderSaveArgs args) { var filePath = FilePathCalculator.Calculate(args); + + if (!args.OverrideExisting && await ExistsAsync(filePath)) + { + throw new BlobAlreadyExistsException($"Saving BLOB '{args.BlobName}' does already exists in the container '{args.ContainerName}'! Set {nameof(args.OverrideExisting)} if it should be overwritten."); + } DirectoryHelper.CreateIfNotExists(Path.GetDirectoryName(filePath)); @@ -29,8 +34,6 @@ namespace Volo.Abp.BlobStoring.FileSystem using (var fileStream = File.Open(filePath, fileMode, FileAccess.Write)) { - //TODO: Truely implement this (like this? http://writeasync.net/?p=2621 or https://www.infoworld.com/article/2995387/how-to-perform-asynchronous-file-operations-in-c.html) - await args.BlobStream.CopyToAsync( fileStream, args.CancellationToken @@ -43,15 +46,13 @@ namespace Volo.Abp.BlobStoring.FileSystem public override Task DeleteAsync(BlobProviderDeleteArgs args) { var filePath = FilePathCalculator.Calculate(args); - return Task.FromResult(FileHelper.DeleteIfExists(filePath)); } public override Task ExistsAsync(BlobProviderExistsArgs args) { var filePath = FilePathCalculator.Calculate(args); - - return Task.FromResult(File.Exists(filePath)); + return ExistsAsync(filePath); } public override Task GetOrNullAsync(BlobProviderGetArgs args) @@ -65,5 +66,10 @@ namespace Volo.Abp.BlobStoring.FileSystem return Task.FromResult(File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)); } + + protected virtual Task ExistsAsync(string filePath) + { + return Task.FromResult(File.Exists(filePath)); + } } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobAlreadyExistsException.cs b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobAlreadyExistsException.cs new file mode 100644 index 0000000000..51eaf29783 --- /dev/null +++ b/framework/src/Volo.Abp.BlobStoring/Volo/Abp/BlobStoring/BlobAlreadyExistsException.cs @@ -0,0 +1,31 @@ +using System; +using System.Runtime.Serialization; + +namespace Volo.Abp.BlobStoring +{ + public class BlobAlreadyExistsException : AbpException + { + public BlobAlreadyExistsException() + { + + } + + public BlobAlreadyExistsException(string message) + : base(message) + { + + } + + public BlobAlreadyExistsException(string message, Exception innerException) + : base(message, innerException) + { + + } + + public BlobAlreadyExistsException(SerializationInfo serializationInfo, StreamingContext context) + : base(serializationInfo, context) + { + + } + } +} \ 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 b995e18785..091c1b7c95 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 @@ -36,6 +36,35 @@ namespace Volo.Abp.BlobStoring var result = await Container.GetAllBytesAsync(blobName); result.SequenceEqual(testContent).ShouldBeTrue(); } + + [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(); + } + + [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(() => + Container.SaveAsync(blobName, testContentOverwritten) + ); + } [Theory] [InlineData("test-blob-1")]