2024-11-10 16:57:24 -05:00
|
|
|
|
using System.Text;
|
2024-11-11 11:37:02 -05:00
|
|
|
|
using OpenHarbor.Storage.Abstractions;
|
2024-11-10 16:57:24 -05:00
|
|
|
|
|
|
|
|
|
namespace OpenHarbor.Storage.Physical;
|
|
|
|
|
|
|
|
|
|
public class PhysicalStorageProvider : IStorageProvider
|
|
|
|
|
{
|
|
|
|
|
public Task<IDirectoryInfo> CreateDirectoryAsync(string path, CancellationToken cancellationToken)
|
|
|
|
|
{
|
|
|
|
|
Directory.CreateDirectory(path);
|
|
|
|
|
|
|
|
|
|
var result = new PhysicalDirectoryInfo(path);
|
|
|
|
|
return Task.FromResult<IDirectoryInfo>(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<bool> FileExistsAsync(string path, CancellationToken cancellationToken) =>
|
|
|
|
|
Task.FromResult(File.Exists(path));
|
|
|
|
|
|
|
|
|
|
public Task<List<IDirectoryInfo>> GetDirectoriesAsync(string path, CancellationToken cancellationToken)
|
|
|
|
|
{
|
|
|
|
|
var directoryInfo = new DirectoryInfo(path);
|
|
|
|
|
var directories = directoryInfo.GetDirectories();
|
|
|
|
|
|
|
|
|
|
var directoriesConverted = directories.Select(t => new PhysicalDirectoryInfo(t.FullName)).AsEnumerable<IDirectoryInfo>().ToList();
|
|
|
|
|
return Task.FromResult(directoriesConverted);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task<byte[]> GetFileBytesAsync(string path, CancellationToken cancellationToken)
|
|
|
|
|
{
|
|
|
|
|
await ThrowNotExistingAsync(path, cancellationToken);
|
|
|
|
|
return await File.ReadAllBytesAsync(path, cancellationToken);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task<string> GetFileContentAsync(string path, Encoding encoding, CancellationToken cancellationToken)
|
|
|
|
|
{
|
|
|
|
|
await ThrowNotExistingAsync(path, cancellationToken);
|
|
|
|
|
return await File.ReadAllTextAsync(path, encoding, cancellationToken);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Task<List<IFileInfo>> 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<IFileInfo>()
|
|
|
|
|
.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<Stream> GetFileStreamAsync(string path, CancellationToken cancellationToken)
|
|
|
|
|
{
|
|
|
|
|
await ThrowNotExistingAsync(path, cancellationToken);
|
|
|
|
|
return new FileStream(path, FileMode.Open, FileAccess.Read);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task<List<IDirectoryOrFile>> GetListAsync(string path, CancellationToken cancellationToken)
|
|
|
|
|
{
|
|
|
|
|
var files = await GetFilesAsync(path, cancellationToken: cancellationToken);
|
|
|
|
|
var directories = await GetDirectoriesAsync(path, cancellationToken: cancellationToken);
|
|
|
|
|
var result = files.AsEnumerable<IDirectoryOrFile>()
|
|
|
|
|
.Concat(directories.AsEnumerable<IDirectoryOrFile>())
|
|
|
|
|
.ToList();
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task<IFileInfo> 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<IFileInfo> 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<IFileInfo> 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<IFileInfo> WriteFileAsync(string sourcePath, string path, bool overrideIfExists = true, CancellationToken cancellationToken = default)
|
|
|
|
|
{
|
|
|
|
|
return WriteFileAsync(sourcePath, path, new DefaultWriteOptions
|
|
|
|
|
{
|
|
|
|
|
OverrideIfExists = overrideIfExists
|
|
|
|
|
}, cancellationToken);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Task<IFileInfo> WriteFileAsync(byte[] bytes, string path, bool overrideIfExists = true, CancellationToken cancellationToken = default)
|
|
|
|
|
{
|
|
|
|
|
return WriteFileAsync(bytes, path, new DefaultWriteOptions
|
|
|
|
|
{
|
|
|
|
|
OverrideIfExists = overrideIfExists
|
|
|
|
|
}, cancellationToken);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Task<IFileInfo> WriteFileAsync(Stream stream, string path, bool overrideIfExists = true, CancellationToken cancellationToken = default)
|
|
|
|
|
{
|
|
|
|
|
return WriteFileAsync(stream, path, new DefaultWriteOptions
|
|
|
|
|
{
|
|
|
|
|
OverrideIfExists = overrideIfExists
|
|
|
|
|
}, cancellationToken);
|
|
|
|
|
}
|
|
|
|
|
}
|