using System.Text; using OpenHarbor.Storage.Abstractions; namespace OpenHarbor.Storage.Physical; public class PhysicalStorageProvider : IStorageProvider { public Task CreateDirectoryAsync(string path, CancellationToken cancellationToken) { Directory.CreateDirectory(path); var result = new PhysicalDirectoryInfo(path); return Task.FromResult(result); } public Task DeleteDirectoryAsync(string path, bool force = false, CancellationToken cancellationToken = default) { if (force) Directory.Delete(path, true); else Directory.Delete(path); return Task.CompletedTask; } public Task DeleteFileAsync(string path, CancellationToken cancellationToken) { File.Delete(path); return Task.CompletedTask; } public Task FileExistsAsync(string path, CancellationToken cancellationToken) => Task.FromResult(File.Exists(path)); public Task> GetDirectoriesAsync(string path, CancellationToken cancellationToken) { var directoryInfo = new DirectoryInfo(path); var directories = directoryInfo.GetDirectories(); var directoriesConverted = directories.Select(t => new PhysicalDirectoryInfo(t.FullName)).AsEnumerable().ToList(); return Task.FromResult(directoriesConverted); } public async Task GetFileBytesAsync(string path, CancellationToken cancellationToken) { await ThrowNotExistingAsync(path, cancellationToken); return await File.ReadAllBytesAsync(path, cancellationToken); } public async Task GetFileContentAsync(string path, Encoding encoding, CancellationToken cancellationToken) { await ThrowNotExistingAsync(path, cancellationToken); return await File.ReadAllTextAsync(path, encoding, cancellationToken); } public Task> GetFilesAsync(string path, string? pattern = null, SearchOption searchOption = SearchOption.TopDirectoryOnly, CancellationToken cancellationToken = default) { var directoryInfo = new DirectoryInfo(path); FileInfo[] files; if (string.IsNullOrWhiteSpace(pattern)) files = directoryInfo.GetFiles(); else files = directoryInfo.GetFiles(pattern, searchOption); var result = files .Select(fileInfo => new PhysicalFileInfo(fileInfo)) .AsEnumerable() .ToList(); return Task.FromResult(result); } private async Task ThrowNotExistingAsync(string path, CancellationToken cancellationToken) { if (false == await FileExistsAsync(path, cancellationToken)) throw new FileDoesNotExistException(path); } public async Task GetFileStreamAsync(string path, CancellationToken cancellationToken) { await ThrowNotExistingAsync(path, cancellationToken); return new FileStream(path, FileMode.Open, FileAccess.Read); } public async Task> GetListAsync(string path, CancellationToken cancellationToken) { var files = await GetFilesAsync(path, cancellationToken: cancellationToken); var directories = await GetDirectoriesAsync(path, cancellationToken: cancellationToken); var result = files.AsEnumerable() .Concat(directories.AsEnumerable()) .ToList(); return result; } public async Task WriteFileAsync(string sourcePath, string path, IWriteFileOptions options, CancellationToken cancellationToken) { ArgumentNullException.ThrowIfNull(options); if (!options.OverrideIfExists && await FileExistsAsync(path, cancellationToken)) throw new FileAlreadyExistsException(path); CreateDirectoryIfNotExisting(path); 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, IWriteFileOptions options, CancellationToken cancellationToken) { if (options is null) throw new ArgumentNullException(nameof(options)); if (!options.OverrideIfExists && await FileExistsAsync(path, cancellationToken)) throw new FileAlreadyExistsException(path); CreateDirectoryIfNotExisting(path); await File.WriteAllBytesAsync(path, bytes, cancellationToken); var fileInfo = new FileInfo(path); var physicalFileInfo = new PhysicalFileInfo(fileInfo); return physicalFileInfo; } public async Task WriteFileAsync(Stream stream, string path, IWriteFileOptions options, CancellationToken cancellationToken) { ArgumentNullException.ThrowIfNull(options); if (!options.OverrideIfExists && await FileExistsAsync(path, cancellationToken)) throw new FileAlreadyExistsException(path); CreateDirectoryIfNotExisting(path); if (stream.CanSeek && stream.Position != 0) stream.Seek(0, SeekOrigin.Begin); await using (var fileStream = new FileStream(path, FileMode.CreateNew, FileAccess.Write)) { await stream.CopyToAsync(fileStream, cancellationToken); fileStream.Close(); } var fileInfo = new FileInfo(path); var physicalinfo = new PhysicalFileInfo(fileInfo); return physicalinfo; } private static void CreateDirectoryIfNotExisting(string path) { var directoryPath = Path.GetDirectoryName(path); if (directoryPath == null) return; if (false == Directory.Exists(directoryPath)) Directory.CreateDirectory(directoryPath); } public bool IsFileNameAllowed(string fileName) => true; public string SanitizeFileName(string key, string replacement) => key; public Task WriteFileAsync(string sourcePath, string path, bool overrideIfExists = true, CancellationToken cancellationToken = default) { return WriteFileAsync(sourcePath, path, new DefaultWriteOptions { OverrideIfExists = overrideIfExists }, cancellationToken); } public Task WriteFileAsync(byte[] bytes, string path, bool overrideIfExists = true, CancellationToken cancellationToken = default) { return WriteFileAsync(bytes, path, new DefaultWriteOptions { OverrideIfExists = overrideIfExists }, cancellationToken); } public Task WriteFileAsync(Stream stream, string path, bool overrideIfExists = true, CancellationToken cancellationToken = default) { return WriteFileAsync(stream, path, new DefaultWriteOptions { OverrideIfExists = overrideIfExists }, cancellationToken); } }