Skip to content

Commit

Permalink
Simplify FolderFileStorage.GetFileStreamAsync
Browse files Browse the repository at this point in the history
  • Loading branch information
ejsmith committed Jan 25, 2024
1 parent 9b89ba9 commit dbfc2a1
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 65 deletions.
4 changes: 2 additions & 2 deletions src/Foundatio.DataProtection/FoundatioStorageXmlRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ private async Task<IReadOnlyCollection<XElement>> GetAllElementsAsync()
return new XElement[0];
}

_logger.LogTrace("Found {FileCount} elements.", files.Count);
_logger.LogTrace("Found {FileCount} elements", files.Count);
var elements = new List<XElement>(files.Count);
foreach (var file in files)
{
_logger.LogTrace("Loading element: {File}", file.Path);
using (var stream = await _storage.GetFileStreamAsync(file.Path).AnyContext())
using (var stream = await _storage.GetFileStreamAsync(file.Path, StreamMode.Read).AnyContext())
{
elements.Add(XElement.Load(stream));
}
Expand Down
11 changes: 6 additions & 5 deletions src/Foundatio.TestHarness/Storage/FileStorageTestsBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -257,21 +257,22 @@ public virtual async Task CanSaveFilesAsync()
string readmeFile = GetTestFilePath();
using (storage)
{
Assert.False(await storage.ExistsAsync("Foundatio.Tests.csproj"));
const string path = "cansavefiles.txt";
Assert.False(await storage.ExistsAsync(path));

await using (var stream = new NonSeekableStream(File.Open(readmeFile, FileMode.Open, FileAccess.Read)))
{
bool result = await storage.SaveFileAsync("Foundatio.Tests.csproj", stream);
bool result = await storage.SaveFileAsync(path, stream);
Assert.True(result);
}

Assert.Single(await storage.GetFileListAsync());
Assert.True(await storage.ExistsAsync("Foundatio.Tests.csproj"));
Assert.True(await storage.ExistsAsync(path));

await using (var stream = await storage.GetFileStreamAsync("Foundatio.Tests.csproj"))
await using (var stream = await storage.GetFileStreamAsync(path, StreamMode.Read))
{
string result = await new StreamReader(stream).ReadToEndAsync();
Assert.Equal(File.ReadAllText(readmeFile), result);
Assert.Equal(await File.ReadAllTextAsync(readmeFile), result);
}
}
}
Expand Down
69 changes: 11 additions & 58 deletions src/Foundatio/Storage/FolderFileStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,51 +52,16 @@ public Task<Stream> GetFileStreamAsync(string path, CancellationToken cancellati
=> GetFileStreamAsync(path, StreamMode.Read, cancellationToken);

public Task<Stream> GetFileStreamAsync(string path, StreamMode streamMode, CancellationToken cancellationToken = default)
{
var stream = streamMode switch
{
StreamMode.Read => GetFileStreamAsync(path, FileAccess.Read),
StreamMode.Write => GetFileStreamAsync(path, FileAccess.Write),
_ => throw new NotSupportedException($"Stream mode {streamMode} is not supported."),
};

return Task.FromResult(stream);
}

public Stream GetFileStreamAsync(string path, FileAccess fileAccess)
{
if (String.IsNullOrEmpty(path))
throw new ArgumentNullException(nameof(path));

string normalizedPath = path.NormalizePath();
string fullPath = Path.Combine(Folder, normalizedPath);
if (fileAccess != FileAccess.Read)
{
CreateFileStream(fullPath).Dispose();
}

var fileMode = GetFileModeForFileAccess(fileAccess);
EnsureDirectory(fullPath);

try
{
return File.Open(fullPath, fileMode, fileAccess);
}
catch (IOException ex) when (ex is FileNotFoundException or DirectoryNotFoundException)
{
_logger.LogError(ex, "Unable to get file stream for {Path}: {Message}", normalizedPath, ex.Message);
return null;
}
}

private FileMode GetFileModeForFileAccess(FileAccess fileAccess)
{
return fileAccess switch
{
FileAccess.Read => FileMode.Open,
FileAccess.Write => FileMode.Create,
FileAccess.ReadWrite => FileMode.OpenOrCreate,
_ => throw new ArgumentOutOfRangeException(nameof(fileAccess), fileAccess, null)
};
var stream = streamMode == StreamMode.Read ? File.OpenRead(fullPath) : File.OpenWrite(fullPath);
return Task.FromResult<Stream>(stream);
}

public Task<FileSpec> GetFileInfoAsync(string path)
Expand Down Expand Up @@ -140,39 +105,27 @@ public async Task<bool> SaveFileAsync(string path, Stream stream, CancellationTo
if (stream == null)
throw new ArgumentNullException(nameof(stream));

string normalizedPath = path.NormalizePath();
_logger.LogTrace("Saving {Path}", normalizedPath);
string file = Path.Combine(Folder, normalizedPath);

try
{
using var fileStream = CreateFileStream(file);
using var fileStream = await GetFileStreamAsync(path, StreamMode.Write, cancellationToken);
await stream.CopyToAsync(fileStream).AnyContext();
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error saving {Path}: {Message}", normalizedPath, ex.Message);
_logger.LogError(ex, "Error saving {Path}: {Message}", path, ex.Message);
return false;
}
}

private Stream CreateFileStream(string filePath)
private void EnsureDirectory(string normalizedPath)
{
try
{
return File.Create(filePath);
}
catch (DirectoryNotFoundException) { }

string directory = Path.GetDirectoryName(filePath);
if (directory != null)
{
_logger.LogInformation("Creating {Directory} directory", directory);
Directory.CreateDirectory(directory);
}
string directory = Path.GetDirectoryName(normalizedPath);
if (directory == null)
return;

return File.Create(filePath);
_logger.LogTrace("Ensuring director: {Directory}", directory);
Directory.CreateDirectory(directory);
}

public async Task<bool> RenameFileAsync(string path, string newPath, CancellationToken cancellationToken = default)
Expand Down

0 comments on commit dbfc2a1

Please sign in to comment.