From f7bfdc18e8f1b0793a1ee2bf8947b3bd9831934b Mon Sep 17 00:00:00 2001 From: David Lebee Date: Tue, 27 Oct 2020 16:04:07 -0400 Subject: [PATCH] Write Options. --- .../Blob/AzureBlobStorageProvider.cs | 93 +++++++++++++------ PoweredSoft.Storage.Core/IStorageProvider.cs | 4 + PoweredSoft.Storage.Core/IWriteFileOptions.cs | 12 +++ .../PhysicalStorageProvider.cs | 54 +++++++++-- PoweredSoft.Storage.S3/IS3FileWriteOptions.cs | 17 ++++ PoweredSoft.Storage.S3/S3StorageProvider.cs | 51 ++++++++-- PoweredSoft.Storage.Test/S3Tests.cs | 20 +++- 7 files changed, 205 insertions(+), 46 deletions(-) create mode 100644 PoweredSoft.Storage.Core/IWriteFileOptions.cs create mode 100644 PoweredSoft.Storage.S3/IS3FileWriteOptions.cs diff --git a/PoweredSoft.Storage.Azure/Blob/AzureBlobStorageProvider.cs b/PoweredSoft.Storage.Azure/Blob/AzureBlobStorageProvider.cs index 487f97d..232d500 100644 --- a/PoweredSoft.Storage.Azure/Blob/AzureBlobStorageProvider.cs +++ b/PoweredSoft.Storage.Azure/Blob/AzureBlobStorageProvider.cs @@ -146,40 +146,28 @@ namespace PoweredSoft.Storage.Azure.Blob return ret; } - public async Task WriteFileAsync(string sourcePath, string path, bool overrideIfExists = true) + public Task WriteFileAsync(string sourcePath, string path, bool overrideIfExists = true) { - if (!overrideIfExists && await FileExistsAsync(path)) - throw new FileAlreadyExistsException(path); - - var container = GetContainer(); - var blob = container.GetBlockBlobReference(path); - await blob.UploadFromFileAsync(sourcePath); - return new AzureBlobFileInfo(blob); + return WriteFileAsync(sourcePath, path, new DefaultWriteOptions + { + OverrideIfExists = overrideIfExists + }); } - public async Task WriteFileAsync(byte[] bytes, string path, bool overrideIfExists = true) + public Task WriteFileAsync(byte[] bytes, string path, bool overrideIfExists = true) { - if (!overrideIfExists && await FileExistsAsync(path)) - throw new FileAlreadyExistsException(path); - - var container = GetContainer(); - var blob = container.GetBlockBlobReference(path); - await blob.UploadFromByteArrayAsync(bytes, 0, bytes.Length); - return new AzureBlobFileInfo(blob); + return WriteFileAsync(bytes, path, new DefaultWriteOptions + { + OverrideIfExists = overrideIfExists + }); } - public async Task WriteFileAsync(Stream stream, string path, bool overrideIfExists = true) + public Task WriteFileAsync(Stream stream, string path, bool overrideIfExists = true) { - if (!overrideIfExists && await FileExistsAsync(path)) - throw new FileAlreadyExistsException(path); - - if (stream.CanSeek && stream.Position != 0) - stream.Seek(0, SeekOrigin.Begin); - - var container = GetContainer(); - var blob = container.GetBlockBlobReference(path); - await blob.UploadFromStreamAsync(stream); - return new AzureBlobFileInfo(blob); + return WriteFileAsync(stream, path, new DefaultWriteOptions + { + OverrideIfExists = overrideIfExists + }); } public async Task GetFileStreamAsync(string path) @@ -222,5 +210,56 @@ namespace PoweredSoft.Storage.Azure.Blob { return key; } + + public async Task WriteFileAsync(string sourcePath, string path, IWriteFileOptions options) + { + if (options is null) + { + throw new ArgumentNullException(nameof(options)); + } + + if (!options.OverrideIfExists && await FileExistsAsync(path)) + throw new FileAlreadyExistsException(path); + + var container = GetContainer(); + var blob = container.GetBlockBlobReference(path); + await blob.UploadFromFileAsync(sourcePath); + return new AzureBlobFileInfo(blob); + } + + public async Task WriteFileAsync(byte[] bytes, string path, IWriteFileOptions options) + { + if (options is null) + { + throw new ArgumentNullException(nameof(options)); + } + + if (!options.OverrideIfExists && await FileExistsAsync(path)) + throw new FileAlreadyExistsException(path); + + var container = GetContainer(); + var blob = container.GetBlockBlobReference(path); + await blob.UploadFromByteArrayAsync(bytes, 0, bytes.Length); + return new AzureBlobFileInfo(blob); + } + + public async Task WriteFileAsync(Stream stream, string path, IWriteFileOptions options) + { + if (options is null) + { + throw new ArgumentNullException(nameof(options)); + } + + if (!options.OverrideIfExists && await FileExistsAsync(path)) + throw new FileAlreadyExistsException(path); + + if (stream.CanSeek && stream.Position != 0) + stream.Seek(0, SeekOrigin.Begin); + + var container = GetContainer(); + var blob = container.GetBlockBlobReference(path); + await blob.UploadFromStreamAsync(stream); + return new AzureBlobFileInfo(blob); + } } } diff --git a/PoweredSoft.Storage.Core/IStorageProvider.cs b/PoweredSoft.Storage.Core/IStorageProvider.cs index 68e7281..a8a445d 100644 --- a/PoweredSoft.Storage.Core/IStorageProvider.cs +++ b/PoweredSoft.Storage.Core/IStorageProvider.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; namespace PoweredSoft.Storage.Core { + public interface IStorageProvider { Task> GetListAsync(string path); @@ -13,6 +14,9 @@ namespace PoweredSoft.Storage.Core Task WriteFileAsync(string sourcePath, string path, bool overrideIfExists = true); Task WriteFileAsync(byte[] bytes, string path, bool overrideIfExists = true); Task WriteFileAsync(Stream stream, string path, bool overrideIfExists = true); + Task WriteFileAsync(string sourcePath, string path, IWriteFileOptions options); + Task WriteFileAsync(byte[] bytes, string path, IWriteFileOptions options); + Task WriteFileAsync(Stream stream, string path, IWriteFileOptions options); Task GetFileStreamAsync(string path); Task GetFileBytesAsync(string path); Task GetFileContentAsync(string path, Encoding encoding); diff --git a/PoweredSoft.Storage.Core/IWriteFileOptions.cs b/PoweredSoft.Storage.Core/IWriteFileOptions.cs new file mode 100644 index 0000000..feaca64 --- /dev/null +++ b/PoweredSoft.Storage.Core/IWriteFileOptions.cs @@ -0,0 +1,12 @@ +namespace PoweredSoft.Storage.Core +{ + public interface IWriteFileOptions + { + bool OverrideIfExists { get; } + } + + public class DefaultWriteOptions : IWriteFileOptions + { + public bool OverrideIfExists { get; set; } + } +} diff --git a/PoweredSoft.Storage.Physical/PhysicalStorageProvider.cs b/PoweredSoft.Storage.Physical/PhysicalStorageProvider.cs index 514992c..97816e4 100644 --- a/PoweredSoft.Storage.Physical/PhysicalStorageProvider.cs +++ b/PoweredSoft.Storage.Physical/PhysicalStorageProvider.cs @@ -92,22 +92,33 @@ namespace PoweredSoft.Storage.Physical return result; } - public async Task WriteFileAsync(string sourcePath, string path, bool overrideIfExists = true) + public async Task WriteFileAsync(string sourcePath, string path, IWriteFileOptions options) { - if (!overrideIfExists && await FileExistsAsync(path)) + if (options is null) + { + throw new ArgumentNullException(nameof(options)); + } + + if (!options.OverrideIfExists && await FileExistsAsync(path)) throw new FileAlreadyExistsException(path); + CreateDirectoryIfNotExisting(path); - System.IO.File.Copy(sourcePath, path, overrideIfExists); + System.IO.File.Copy(sourcePath, path, options.OverrideIfExists); var fileInfo = new FileInfo(path); var ret = new PhysicalFileInfo(fileInfo); return ret; } - public async Task WriteFileAsync(byte[] bytes, string path, bool overrideIfExists = true) + public async Task WriteFileAsync(byte[] bytes, string path, IWriteFileOptions options) { - if (!overrideIfExists && await FileExistsAsync(path)) + if (options is null) + { + throw new ArgumentNullException(nameof(options)); + } + + if (!options.OverrideIfExists && await FileExistsAsync(path)) throw new FileAlreadyExistsException(path); CreateDirectoryIfNotExisting(path); @@ -118,9 +129,14 @@ namespace PoweredSoft.Storage.Physical return physicalinfo; } - public async Task WriteFileAsync(Stream stream, string path, bool overrideIfExists = true) + public async Task WriteFileAsync(Stream stream, string path, IWriteFileOptions options) { - if (!overrideIfExists && await FileExistsAsync(path)) + if (options is null) + { + throw new ArgumentNullException(nameof(options)); + } + + if (!options.OverrideIfExists && await FileExistsAsync(path)) throw new FileAlreadyExistsException(path); CreateDirectoryIfNotExisting(path); @@ -155,5 +171,29 @@ namespace PoweredSoft.Storage.Physical { return key; } + + public Task WriteFileAsync(string sourcePath, string path, bool overrideIfExists = true) + { + return WriteFileAsync(sourcePath, path, new DefaultWriteOptions + { + OverrideIfExists = overrideIfExists + }); + } + + public Task WriteFileAsync(byte[] bytes, string path, bool overrideIfExists = true) + { + return WriteFileAsync(bytes, path, new DefaultWriteOptions + { + OverrideIfExists = overrideIfExists + }); + } + + public Task WriteFileAsync(Stream stream, string path, bool overrideIfExists = true) + { + return WriteFileAsync(stream, path, new DefaultWriteOptions + { + OverrideIfExists = overrideIfExists + }); + } } } diff --git a/PoweredSoft.Storage.S3/IS3FileWriteOptions.cs b/PoweredSoft.Storage.S3/IS3FileWriteOptions.cs new file mode 100644 index 0000000..7f436ea --- /dev/null +++ b/PoweredSoft.Storage.S3/IS3FileWriteOptions.cs @@ -0,0 +1,17 @@ +using PoweredSoft.Storage.Core; +using System; +using System.Collections.Generic; +using System.Text; + +namespace PoweredSoft.Storage.S3 +{ + public interface IS3FileWriteOptions + { + public string Acl { get; } + } + + public class S3FileWriteOptions : DefaultWriteOptions, IS3FileWriteOptions + { + public string Acl { get; set; } + } +} diff --git a/PoweredSoft.Storage.S3/S3StorageProvider.cs b/PoweredSoft.Storage.S3/S3StorageProvider.cs index be29eb5..11d99f1 100644 --- a/PoweredSoft.Storage.S3/S3StorageProvider.cs +++ b/PoweredSoft.Storage.S3/S3StorageProvider.cs @@ -177,22 +177,25 @@ namespace PoweredSoft.Storage.S3 return files.Cast().ToList(); } - public async Task WriteFileAsync(string sourcePath, string path, bool overrideIfExists = true) + public async Task WriteFileAsync(string sourcePath, string path, IWriteFileOptions options) { - using var client = GetClient(); - await client.UploadObjectFromFilePathAsync(this.bucketName, path, sourcePath, null); - var file = await GetFileInfoByPath(path); - return file; + using var fileStream = new FileStream(sourcePath, FileMode.Open, FileAccess.Read); + return await WriteFileAsync(fileStream, path, options); } - public Task WriteFileAsync(byte[] bytes, string path, bool overrideIfExists = true) + public Task WriteFileAsync(byte[] bytes, string path, IWriteFileOptions options) { - return WriteFileAsync(new MemoryStream(bytes), path, overrideIfExists: overrideIfExists); + return WriteFileAsync(new MemoryStream(bytes), path, options); } - public async Task WriteFileAsync(Stream stream, string path, bool overrideIfExists = true) + public async Task WriteFileAsync(Stream stream, string path, IWriteFileOptions options) { - if (!overrideIfExists && await FileExistsAsync(path)) + if (options is null) + { + throw new ArgumentNullException(nameof(options)); + } + + if (!options.OverrideIfExists && await FileExistsAsync(path)) throw new FileAlreadyExistsException(path); using var client = GetClient(); @@ -203,6 +206,12 @@ namespace PoweredSoft.Storage.S3 Key = path }; + if (options is IS3FileWriteOptions s3FileWriteOptions) + { + if (s3FileWriteOptions.Acl != null) + request.CannedACL = new S3CannedACL(s3FileWriteOptions.Acl); + } + var result = await client.PutObjectAsync(request); var file = await GetFileInfoByPath(path); return file; @@ -246,5 +255,29 @@ namespace PoweredSoft.Storage.S3 var hasMatches = regex.IsMatch(fileName); return false == hasMatches; } + + public Task WriteFileAsync(string sourcePath, string path, bool overrideIfExists = true) + { + return WriteFileAsync(sourcePath, path, new DefaultWriteOptions + { + OverrideIfExists = overrideIfExists + }); + } + + public Task WriteFileAsync(byte[] bytes, string path, bool overrideIfExists = true) + { + return WriteFileAsync(bytes, path, new DefaultWriteOptions + { + OverrideIfExists = overrideIfExists + }); + } + + public Task WriteFileAsync(Stream stream, string path, bool overrideIfExists = true) + { + return WriteFileAsync(stream, path, new DefaultWriteOptions + { + OverrideIfExists = overrideIfExists + }); + } } } diff --git a/PoweredSoft.Storage.Test/S3Tests.cs b/PoweredSoft.Storage.Test/S3Tests.cs index 0415b69..0512087 100644 --- a/PoweredSoft.Storage.Test/S3Tests.cs +++ b/PoweredSoft.Storage.Test/S3Tests.cs @@ -1,11 +1,23 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using PoweredSoft.Storage.S3; +using System.Text; namespace PoweredSoft.Storage.Test { [TestClass] public class S3Tests { + [TestMethod] + public async System.Threading.Tasks.Task S3AclWriteAsync() + { + var space = GetMockS3Space(); + await space.WriteFileAsync(Encoding.UTF8.GetBytes("Hello World"), "hello-world.txt", new S3FileWriteOptions + { + Acl = "public-read", + OverrideIfExists = true + }); + } + [TestMethod] public void NameValidation() { @@ -33,9 +45,11 @@ namespace PoweredSoft.Storage.Test private static S3StorageProvider GetMockS3Space() { - var space = new S3StorageProvider("http://localhost:9000", "mybucket", "myminio", "myexample"); - space.SetForcePathStyle(true); - space.SetS3UsEast1RegionalEndpointValue(Amazon.Runtime.S3UsEast1RegionalEndpointValue.Legacy); + //var space = new S3StorageProvider("http://localhost:9000", "mybucket", "minioadmin", "minioadmin"); + //space.SetForcePathStyle(true); + //space.SetS3UsEast1RegionalEndpointValue(Amazon.Runtime.S3UsEast1RegionalEndpointValue.Legacy); + + var space = new S3StorageProvider(" https://nyc3.digitaloceanspaces.com", "lveb-public", "42ZNGWW3EHQECLS7FCPT", "NKhVtWvAdUKRhoFN9QK7rsqnLarVaxpxIAwHJTCPrIA"); return space; } }