File Storage
Strategy pattern with 4 providers (Local, Azure Blob, AWS S3, MinIO) with tenant-scoped directories.
SCRIPE uses the Strategy pattern for file storage, allowing seamless switching between local filesystem, Azure Blob Storage, AWS S3, and MinIO. All storage is tenant-scoped with configurable directories.
Storage Architecture
LocalFileStorage — wwwroot/ filesystem
AzureBlobStorage — Azure Blob Containers
AwsS3Storage — AWS S3 Buckets
MinIOStorage — Self-hosted S3-compatible
implements
IFileStorageService — Abstraction interface
IFileStorageService Interface
IFileStorageService — ContractC#
public interface IFileStorageService
{
Task<string> UploadAsync(Stream stream, string fileName,
string folder, CancellationToken ct = default);
Task<Stream?> DownloadAsync(string path,
CancellationToken ct = default);
Task<bool> DeleteAsync(string path,
CancellationToken ct = default);
Task<bool> ExistsAsync(string path,
CancellationToken ct = default);
Task<FileMetadata> GetMetadataAsync(string path,
CancellationToken ct = default);
string GetPublicUrl(string path);
}Storage Provider Implementations
appsettings.json — LocalJSON
{
"FileStorage": {
"Provider": "Local",
"Local": {
"BasePath": "wwwroot/uploads",
"RequestPath": "/uploads",
"MaxFileSizeMB": 10,
"AllowedExtensions": [".jpg", ".png", ".pdf", ".docx"]
}
}
}File Upload & Processing Pipeline
Upload Flow with ValidationC#
// In Controller
[HttpPost("upload")]
[RequestSizeLimit(10_000_000)] // 10 MB
public async Task<IActionResult> Upload(IFormFile file)
{
// 1. Validate file
var validation = _fileValidator.Validate(file);
if (!validation.IsValid)
return BadRequest(validation.Errors);
// 2. Generate safe filename
var safeFileName = $"{Guid.NewGuid()}{Path.GetExtension(file.FileName)}";
// 3. Upload via storage service
var path = await _storage.UploadAsync(
file.OpenReadStream(),
safeFileName,
"avatars", // folder
ct
);
// 4. Return public URL
return Ok(new { url = _storage.GetPublicUrl(path) });
}File Validation
| Validation | Rule | Error Message |
|---|---|---|
| File size | Max 10 MB (configurable) | File exceeds maximum size |
| Image dimensions | Max 4096×4096 px | Image dimensions too large |
| Extension whitelist | .jpg, .png, .gif, .webp, .pdf, .docx | File type not allowed |
| MIME type check | Verify MIME matches extension | File content doesn't match extension |
| Magic bytes | Check file header bytes | Corrupted or fake file detected |
| Filename sanitization | Remove special chars, limit length | Applied automatically |