using System.Text.Json; using DeepDrftContent.Data.FileDatabase.Models; namespace DeepDrftContent.Data.FileDatabase.Utils; /// /// Utility class for file I/O operations, matching the TypeScript file utilities /// public static class FileUtils { /// /// Reads a file and returns it as a FileBinary object /// /// Path to the media file /// FileBinary containing the file data public static async Task FetchFileAsync(string mediaPath) { using var fileStream = new FileStream(mediaPath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 64 * 1024); var buffer = new byte[fileStream.Length]; var totalBytesRead = 0; while (totalBytesRead < fileStream.Length) { var bytesRead = await fileStream.ReadAsync(buffer.AsMemory(totalBytesRead)); if (bytesRead == 0) throw new EndOfStreamException($"Unexpected end of stream while reading {mediaPath}"); totalBytesRead += bytesRead; } return new FileBinary(new FileBinaryParams(buffer, buffer.Length)); } /// /// Writes binary data to a file /// /// Path where to write the file /// Binary data to write public static async Task PutFileAsync(string mediaPath, byte[] buffer) { const int chunkSize = 64 * 1024; using var fileStream = new FileStream(mediaPath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: chunkSize); for (int offset = 0; offset < buffer.Length; offset += chunkSize) { var length = Math.Min(chunkSize, buffer.Length - offset); await fileStream.WriteAsync(buffer.AsMemory(offset, length)); } await fileStream.FlushAsync(); } /// /// Serializes an object to a file using JSON /// /// Path to the file /// Object to serialize public static async Task PutObjectAsync(string filePath, T obj) { var options = new JsonSerializerOptions { WriteIndented = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; var json = JsonSerializer.Serialize(obj, options); await File.WriteAllTextAsync(filePath, json); } /// /// Deserializes an object from a JSON file /// /// Path to the file /// Deserialized object public static async Task FetchObjectAsync(string filePath) { var json = await File.ReadAllTextAsync(filePath); var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; var result = JsonSerializer.Deserialize(json, options); return result ?? throw new InvalidOperationException($"Failed to deserialize object from {filePath}"); } /// /// Creates a directory if it doesn't exist /// /// Path to the directory public static Task MakeVaultDirectoryAsync(string directoryPath) { Directory.CreateDirectory(directoryPath); return Task.CompletedTask; } /// /// Checks if a file exists /// /// Path to check /// True if file exists public static bool FileExists(string filePath) { return File.Exists(filePath); } /// /// Checks if a directory exists /// /// Path to check /// True if directory exists public static bool DirectoryExists(string directoryPath) { return Directory.Exists(directoryPath); } }