public interface IR2FileService { Task UploadFileAsync(IFormFile file, string folderName = ""); Task RetrieveFileAsync(string fileKey); Task DeleteFileAsync(string fileKey); Task RetriveList(); } public class R2FileService : IR2FileService { private readonly IAmazonS3 _s3Client; private readonly string _bucketName; private readonly ILogger _logger; public R2FileService(IConfiguration configuration, ILogger logger) { _logger = logger; var accessKey = configuration["Cloudflare:R2:AccessKey"]; var secretKey = configuration["Cloudflare:R2:SecretKey"]; var accountId = configuration["Cloudflare:R2:AccountId"]; _bucketName = configuration["Cloudflare:R2:BucketName"]; var credentials = new BasicAWSCredentials(accessKey, secretKey); var config = new AmazonS3Config { ServiceURL = $"https://{accountId}.r2.cloudflarestorage.com", ForcePathStyle = true, SignatureVersion = "4" }; _s3Client = new AmazonS3Client(credentials, config); } public async Task UploadFileAsync(IFormFile file, string folderName = "") { try { // Generate a unique file name (you might want to implement your own naming strategy) var fileName = $"{Guid.NewGuid()}{Path.GetExtension(file.FileName)}"; _logger.LogInformation(fileName); // Create the full path including folder if provided var fileKey = string.IsNullOrEmpty(folderName) ? fileName : $"{folderName.TrimEnd('/')}/{fileName}"; using (var fileStream = file.OpenReadStream()) { var transferUtility = new TransferUtility(_s3Client); var uploadRequest = new TransferUtilityUploadRequest { InputStream = fileStream, BucketName = "testing", Key = fileKey, ContentType = file.ContentType, //DisablePayloadSigning = true }; await transferUtility.UploadAsync(uploadRequest); } _logger.LogInformation($"File {fileName} uploaded successfully to {fileKey}"); return fileKey; } catch (Exception ex) { _logger.LogError($"Error uploading file: {ex.Message}"); throw; } }