A focused REST API for file management built with ASP.NET Core (.NET 10) and Cloudinary for cloud storage.
Supports secure file uploads, content-based validation, streaming, listing, and deletion through a clean service-based architecture.
Originally started with local disk storage and later migrated fully to Cloudinary as a production-minded architectural improvement.
The API is deployed on MonsterASP.NET.
Live Swagger Documentation:
http://filemanageer.runasp.net/swagger
| Framework | ASP.NET Core .NET 10 |
| Database | SQL Server |
| ORM | Entity Framework Core |
| Cloud Storage | Cloudinary |
| Validation | FluentValidation |
| API Docs | Swagger / OpenAPI |
| Hosting | MonsterASP.NET |
FileManager.Api/
├── Contracts/
│ ├── Common/
│ └── ...
├── Controllers/
│ └── FilesController.cs
├── Entities/
│ └── UploadedFile.cs
├── Persistence/
│ ├── EntityConfigurations/
│ └── ApplicationDbContext.cs
├── Services/
│ ├── IFileService.cs
│ └── FileService.cs
└── Settings/
└── CloudinarySettings.cs
- Upload single files
- Upload multiple files
- Upload image files
- Stream files directly from Cloudinary
- Delete files from Cloudinary and database
- Content-based validation
- Secure cloud storage architecture
- Clean service-based structure
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/files |
Get all uploaded files |
GET |
/api/files/stream/{id} |
Stream a file from Cloudinary |
POST |
/api/files/upload |
Upload a single file |
POST |
/api/files/upload-many |
Upload multiple files |
POST |
/api/files/upload-image |
Upload image files |
DELETE |
/api/files/{id} |
Delete a file |
All uploaded files go through layered validation before reaching the service layer.
| Rule | Description |
|---|---|
| Required | Rejects null or missing files |
| Size | Maximum 1 MB |
| File Name | Allows only safe characters |
| File Signature | Blocks dangerous file signatures |
| Image Validation | Accepts only valid JPG, JPEG, PNG images |
Validation is content-based, not extension-based.
Renaming a malicious file extension will not bypass validation.
All files are stored in Cloudinary instead of local disk storage.
| Field | Purpose |
|---|---|
PublicId |
Used for Cloudinary deletion |
CloudinaryUrl |
Secure access URL |
ResourceType |
Determines image/raw handling |
- Images use
ImageUploadParams - Non-image files use
RawUploadParams - Streaming uses
IHttpClientFactory - Files are streamed directly from Cloudinary URLs
- Uses
IHttpClientFactoryto avoid socket exhaustion - Uses
AsNoTracking()for read-only queries - Uses async streaming for scalable file handling
- Separates image and raw file upload pipelines
- Removes dependency on local file storage
- Uses secure Cloudinary-hosted access URLs
git clone https://github.com/a7medhazem/FileManager.git
cd FileManager{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=FileManager;Trusted_Connection=True;Encrypt=False"
},
"CloudinarySettings": {
"CloudName": "your-cloud-name",
"ApiKey": "your-api-key",
"ApiSecret": "your-api-secret"
}
}dotnet ef database updatedotnet runThis project is licensed under the MIT License.