- A modular and extensible .NET 7 Web API that provides unified file-storage operations across multiple providers, including Amazon S3 and Azure Blob Storage. The project implements common storage endpoints via a generic controller and provider-specific service implementations.
CloudStorages.Server/
│
├── Configuration/
│ ├── AwsS3Settings.cs
│ └── AzureBlobSettings.cs
│
├── Controllers/
│ ├── AwsS3StorageController.cs
│ ├── AzureBlobStorageController.cs
│ └── StorageController.cs # Generic base controller
│
├── Dtos/
│ ├── Requests/
│ └── Responses/
│
├── Filters/
│ └── DecodeRouteKeyAttribute.cs # Automatically decodes the file key
│
├── Middlewares/
│ └── ExceptionHandlingMiddleware.cs # Global exception handler
│
├── Services/
│ ├── AwsS3StorageService.cs
│ ├── AzureBlobStorageService.cs
│ ├── IAwsS3StorageService.cs
│ ├── IAzureBlobStorageService.cs
│ └── IStorageService.cs # Common interface
│
├── Utils/
│
├── appsettings.json
└── Program.cs
-
All providers implement:
-
Generate upload URL
-
Generate download URL
-
Upload file(s)
-
Download file
-
List all files
-
Delete file
-
Create container
-
List containers
-
Check container existence
-
-
Multipart upload
-
Pre-signed URLs for each upload part
-
Complete multipart upload
-
The base class:
StorageController<TStorageService>
automatically provides all core REST endpoints, so each provider only needs to register its service.
git clone https://github.com/sonnh02-dev/CloudStorages.git
cd CloudStorages.Server
-
.NET SDK 7+
-
Azure CLI (for Key Vault integration)
-
Cloud resources:
- AWS S3 Bucket
- Azure Blob Storage account + container
dotnet restoredotnet build
-
Azure Blob Storage :
-
Azure Key Vault:
-
Azure App Registration
- Create project

- Create an Bucket

- Create an IAM service account** and generate a key to obtain credentials

-
Retrieve secrets
-
Store Secrets in Azure Key Vault
-
Combine secrets with appsettings.json:
{ "AzureKeyVault": { "ClientId": "308e0ee2-ca0a-4b50-94b2-8c8277375fc0", "TenantId": "4d2342ef-8904-4072-843d-e895456a2451", "VaultName": "cloud-storages-kv" }, "AwsS3": { "BucketName": "cloud-storages-bucket", "Region": "ap-southeast-1" }, "AzureBlob": { "AccountName": "cloudstoragessa", "ContainerName": "cloud-storages-container" }, "GoogleCloud": { "BucketName": "cloud-storages-bucket", "ProjectId": "cloudstorages" } } -
Staging (Docker Swarm, Docker Compose, VPS,..) uses ClientSecretCredential because there is no Managed Identity :
if (!string.IsNullOrEmpty(clientSecret) && builder.Environment.IsStaging()) { var credential = new ClientSecretCredential( keyVaultSettings?.TenantId, keyVaultSettings?.ClientId, clientSecret ); // Load secrets from Azure Key Vault into Configuration builder.Configuration.AddAzureKeyVault(keyVaultUri, credential); } -
Production (Azure App Service, Azure Container Apps, AKS,..) uses DefaultAzureCredential to use Managed Identity safely, without needing to save secrets :
builder.Configuration.AddAzureKeyVault(keyVaultUri, new DefaultAzureCredential());
- Swagger UI will be available at:
https://localhost:<port>/swagger - Dependency Injection Setup
Each controller consumes the corresponding service automatically.
builder.Services.AddScoped<IAwsS3StorageService, AwsS3StorageService>(); builder.Services.AddScoped<IAzureBlobStorageService, AzureBlobStorageService>(); ...
This project is open-source for educational and personal use.










