Skip to content

File Storage ​

SimpleModule provides a file storage abstraction with pluggable providers for local filesystem, AWS S3, and Azure Blob Storage. The FileStorage module adds HTTP endpoints, database tracking, and an admin UI on top of this abstraction.

Storage Providers ​

IStorageProvider Interface ​

All providers implement a common interface:

csharp
public interface IStorageProvider
{
    Task<StorageResult> SaveAsync(string path, Stream content, string contentType);
    Task<Stream?> GetAsync(string path);
    Task<bool> DeleteAsync(string path);
    Task<bool> ExistsAsync(string path);
    Task<IReadOnlyList<StorageEntry>> ListAsync(string prefix);
}

Local Storage ​

Stores files on the local filesystem. Best for development and single-server deployments.

csharp
builder.Services.AddLocalStorage(builder.Configuration);
json
{
  "Storage": {
    "Provider": "Local",
    "Local": {
      "BasePath": "./storage"
    }
  }
}

AWS S3 ​

csharp
builder.Services.AddS3Storage(builder.Configuration);
json
{
  "Storage": {
    "Provider": "S3",
    "S3": {
      "BucketName": "my-bucket",
      "AccessKey": "your-access-key",
      "SecretKey": "your-secret-key",
      "Region": "us-east-1",
      "ServiceUrl": "",
      "ForcePathStyle": false
    }
  }
}

Set ServiceUrl for S3-compatible services (MinIO, DigitalOcean Spaces). Set ForcePathStyle to true for path-style URL access.

Azure Blob Storage ​

csharp
builder.Services.AddAzureBlobStorage(builder.Configuration);
json
{
  "Storage": {
    "Provider": "Azure",
    "Azure": {
      "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=...",
      "ContainerName": "files"
    }
  }
}

FileStorage Module ​

The FileStorage module provides HTTP endpoints and a database-backed file registry on top of the storage abstraction.

API Endpoints ​

MethodRoutePermissionDescription
POST/api/files/FileStorage.UploadUpload a file (multipart form)
GET/api/files/FileStorage.ViewList files (optional ?folder= filter)
GET/api/files/{id}FileStorage.ViewGet file metadata by ID
GET/api/files/{id}/downloadFileStorage.ViewDownload file content
DELETE/api/files/{id}FileStorage.DeleteDelete a file
GET/api/files/foldersFileStorage.ViewList folders (optional ?parent= filter)

Browse UI ​

A file browser view at /files/browse lets users navigate folders, upload files, and download or delete existing files.

Module Settings ​

SettingDefaultDescription
FileStorage.MaxFileSizeMb50Maximum upload size in megabytes
FileStorage.AllowedExtensions.jpg,.jpeg,.png,.gif,.pdf,.doc,.docx,.xls,.xlsx,.zipComma-separated allowed file extensions

Using from Other Modules ​

Inject IFileStorageContracts to interact with file storage from any module:

csharp
public interface IFileStorageContracts
{
    Task<IEnumerable<StoredFile>> GetFilesAsync(string? folder = null);
    Task<StoredFile?> GetFileByIdAsync(FileStorageId id);
    Task<StoredFile> UploadFileAsync(
        Stream content, string fileName, string contentType, string? folder = null);
    Task DeleteFileAsync(FileStorageId id);
    Task<Stream?> DownloadFileAsync(FileStorageId id);
    Task<IEnumerable<string>> GetFoldersAsync(string? parentFolder = null);
}

Provider Comparison ​

FeatureLocalS3Azure
External dependenciesNoneAWSSDK.S3Azure.Storage.Blobs
Folder supportPhysical directoriesPrefix-basedPrefix-based
PaginationN/AListObjectsV2GetBlobsByHierarchyAsync
Best forDevelopment, single serverProduction, multi-regionProduction, Azure ecosystem

Path Handling ​

All paths are normalized to forward slashes internally. The StoragePathHelper utility provides safe path operations:

  • Path traversal attacks are blocked (paths cannot escape the base directory)
  • Leading/trailing slashes are normalized
  • File names and folder names are extracted consistently across providers

Next Steps ​

Released under the MIT License.