diff --git a/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo.Abp.BlobStoring.FileSystem.csproj b/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo.Abp.BlobStoring.FileSystem.csproj index 03fcbbd374..88fc08e34e 100644 --- a/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo.Abp.BlobStoring.FileSystem.csproj +++ b/framework/src/Volo.Abp.BlobStoring.FileSystem/Volo.Abp.BlobStoring.FileSystem.csproj @@ -16,6 +16,7 @@ + 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 aafba5b696..cbfe4bcaf7 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 @@ -1,5 +1,7 @@ -using System.IO; +using System; +using System.IO; using System.Threading.Tasks; +using Polly; using Volo.Abp.DependencyInjection; using Volo.Abp.IO; @@ -8,12 +10,12 @@ namespace Volo.Abp.BlobStoring.FileSystem public class FileSystemBlobProvider : BlobProviderBase, ITransientDependency { protected IBlobFilePathCalculator FilePathCalculator { get; } - + public FileSystemBlobProvider(IBlobFilePathCalculator filePathCalculator) { FilePathCalculator = filePathCalculator; } - + public override async Task SaveAsync(BlobProviderSaveArgs args) { var filePath = FilePathCalculator.Calculate(args); @@ -22,22 +24,27 @@ namespace Volo.Abp.BlobStoring.FileSystem { 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)); var fileMode = args.OverrideExisting ? FileMode.Create : FileMode.CreateNew; - - using (var fileStream = File.Open(filePath, fileMode, FileAccess.Write)) - { - await args.BlobStream.CopyToAsync( - fileStream, - args.CancellationToken - ); - await fileStream.FlushAsync(); - } + await Policy.Handle() + .WaitAndRetryAsync(2, retryCount => TimeSpan.FromSeconds(retryCount)) + .ExecuteAsync(async () => + { + using (var fileStream = File.Open(filePath, fileMode, FileAccess.Write)) + { + await args.BlobStream.CopyToAsync( + fileStream, + args.CancellationToken + ); + + await fileStream.FlushAsync(); + } + }); } public override Task DeleteAsync(BlobProviderDeleteArgs args) @@ -52,21 +59,31 @@ namespace Volo.Abp.BlobStoring.FileSystem return ExistsAsync(filePath); } - public override Task GetOrNullAsync(BlobProviderGetArgs args) + public override async Task GetOrNullAsync(BlobProviderGetArgs args) { var filePath = FilePathCalculator.Calculate(args); if (!File.Exists(filePath)) { - return Task.FromResult(null); + return null; } - return Task.FromResult(File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)); + return await Policy.Handle() + .WaitAndRetryAsync(2, retryCount => TimeSpan.FromSeconds(retryCount)) + .ExecuteAsync(async () => + { + using (var fileStream = File.OpenRead(filePath)) + { + var memoryStream = new MemoryStream(); + await fileStream.CopyToAsync(memoryStream, args.CancellationToken); + return memoryStream; + } + }); } - + 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.Core/System/IO/AbpStreamExtensions.cs b/framework/src/Volo.Abp.Core/System/IO/AbpStreamExtensions.cs index 466d73b2a7..bd85773a9b 100644 --- a/framework/src/Volo.Abp.Core/System/IO/AbpStreamExtensions.cs +++ b/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