diff --git a/Frends.File.Tests/UnitTest.cs b/Frends.File.Tests/UnitTest.cs index 0602779..fef1136 100644 --- a/Frends.File.Tests/UnitTest.cs +++ b/Frends.File.Tests/UnitTest.cs @@ -361,6 +361,39 @@ public async Task WriteFileThrow() Assert.Equal("old content", fileContent); Assert.Equal($"File already exists: {Path.Combine(TestFileContext.RootPath, "test.txt")}", ex.Message); } + [Fact] + public async Task WriteFileCreateDirectory() + { + var result = await File.Write( + new WriteInput() + { + Content = "Created with a subdirectory", + Path = Path.Combine(TestFileContext.RootPath, "folder/Subdir/subdir.txt") + }, + new WriteOption() + { + CreateTargetDirectories = true + }); + var fileContent = System.IO.File.ReadAllText(result.Path); + Console.WriteLine(result.Path); + Assert.Equal("Created with a subdirectory", fileContent); + } + + [Fact] + public async Task WriteFileCreateDirectoryThrow() + { + var result = await Assert.ThrowsAsync(async () => await File.Write( + new WriteInput() + { + Content = "Task should throw", + Path = Path.Combine(TestFileContext.RootPath, "folder/Subdir/subdir.txt") + }, + new WriteOption() + { + CreateTargetDirectories = false + })); + + } [Fact] public async Task WriteFileBytesAppend() @@ -430,6 +463,42 @@ public async Task WriteFileBytesThrow() Assert.Equal(imageBytes, fileContentBytes); } + [Fact] + public async Task WriteFileBytesCreateDirectory() + { + var imageBytes = System.IO.File.ReadAllBytes(BinaryTestFilePath); + TestFileContext.CreateBinaryFile("test.png", new byte[] { 137, 80, 78, 71, 13, 10, 26, 10 }); // empty png + var result = await File.WriteBytes( + new WriteBytesInput() + { + ContentBytes = imageBytes, + Path = Path.Combine(TestFileContext.RootPath, "folder/Subdir/test.png") + }, + new WriteBytesOption() + { + CreateTargetDirectories = true, + }); + var fileContentBytes = System.IO.File.ReadAllBytes(result.Path); + Assert.Equal(imageBytes.Length, fileContentBytes.Length); + Assert.Equal(imageBytes, fileContentBytes); + } + [Fact] + public async Task WriteFileBytesCreateDirectoryThrow() + { + var imageBytes = System.IO.File.ReadAllBytes(BinaryTestFilePath); + TestFileContext.CreateBinaryFile("test.png", new byte[] { 137, 80, 78, 71, 13, 10, 26, 10 }); // empty png + var result = await Assert.ThrowsAsync(async () => await File.WriteBytes( + new WriteBytesInput() + { + ContentBytes = imageBytes, + Path = Path.Combine(TestFileContext.RootPath, "folder/Subdir/test.png") + }, + new WriteBytesOption() + { + CreateTargetDirectories = false, + })); + } + [Fact] public async Task ReadFileContent() { diff --git a/Frends.File/Definitions.cs b/Frends.File/Definitions.cs index 6fc1712..018de51 100644 --- a/Frends.File/Definitions.cs +++ b/Frends.File/Definitions.cs @@ -247,6 +247,13 @@ public class WriteOption /// How the file write should work if a file with the new name already exists /// public WriteBehaviour WriteBehaviour { get; set; } + + /// + /// If set, will create the target directory if it does not exist, + /// as well as any sub directories. + /// + [DefaultValue(false)] + public bool CreateTargetDirectories { get; set; } } public class WriteBytesOption @@ -273,6 +280,13 @@ public class WriteBytesOption /// How the file write should work if a file with the new name already exists /// public WriteBehaviour WriteBehaviour { get; set; } + + /// + /// If set, will create the target directory if it does not exist, + /// as well as any sub directories. + /// + [DefaultValue(false)] + public bool CreateTargetDirectories { get; set; } } public class WriteResult diff --git a/Frends.File/File.cs b/Frends.File/File.cs index 9fc67f9..dc138e7 100644 --- a/Frends.File/File.cs +++ b/Frends.File/File.cs @@ -287,6 +287,15 @@ private static async Task ExecuteWrite(WriteInput input, WriteOptio var encoding = GetEncoding(options.FileEncoding, options.EnableBom, options.EncodingInString); var fileMode = GetAndCheckWriteMode(options.WriteBehaviour, input.Path); + if(options.CreateTargetDirectories) + { + var directoryPath = Path.GetDirectoryName(input.Path); + if(!Directory.Exists(directoryPath)) + { + Directory.CreateDirectory(directoryPath); + } + } + using (var fileStream = new FileStream(input.Path, fileMode, FileAccess.Write, FileShare.Write, 4096, useAsync: true)) using (var writer = new StreamWriter(fileStream, encoding)) { @@ -298,6 +307,14 @@ private static async Task ExecuteWrite(WriteInput input, WriteOptio private static async Task ExecuteWriteBytes(WriteBytesInput input, WriteBytesOption options) { + if (options.CreateTargetDirectories) + { + var directoryPath = Path.GetDirectoryName(input.Path); + if (!Directory.Exists(directoryPath)) + { + Directory.CreateDirectory(directoryPath); + } + } var bytes = input?.ContentBytes as byte[] ?? throw new ArgumentException("Input.ContentBytes must be a byte array", nameof(input.ContentBytes)); // TODO: Use corrctly typed input once UI support expression default editor for arrays var fileMode = GetAndCheckWriteMode(options.WriteBehaviour, input.Path);