File Storage
KraftAdmin includes a provider-based storage abstraction that allows uploaded files to be stored using different storage backends without changing your application code.
Whether you choose local disk storage during development or cloud providers such as Amazon S3 or Cloudinary in production, the programming model remains identical.
All media fieldsβincluding images, videos, audio, and documentsβuse the same storage pipeline.
Supported Providers
KraftAdmin currently includes built-in support for:
- Local File System
- Amazon S3
- Cloudinary
Additional providers can easily be implemented by creating a custom storage provider.
Why a Storage Abstraction?
Instead of tightly coupling uploads to a specific cloud platform, KraftAdmin introduces a common interface:
interface AdminStorageProvider Every storage provider implements the same operations:
- Upload files
- Update existing files
- Delete files
- Determine ownership of a file
Because every provider exposes the same contract, switching from local storage to cloud storage requires little or no changes to your entity definitions.
Storage Architecture
Browser
β
βΌ
Multipart Request
β
βΌ
KraftAdmin Resource
β
βΌ
AdminStorageProvider
β
βββββββββββββΌβββββββββββββ
βΌ βΌ βΌ
Local Storage Amazon S3 Cloudinary
β
βΌ
Public File URL
β
βΌ
Persisted in Entity The administration engine never communicates directly with the storage platform.
Instead, it delegates every operation to the configured storage provider.
Upload Lifecycle
When an administrator uploads a file, KraftAdmin performs the following sequence:
Administrator
β
Select File
β
HTTP Multipart Request
β
Validate File
β
AdminStorageProvider.upload()
β
Storage Platform
β
Public URL Returned
β
Entity Saved The returned URL becomes the value stored inside your entity.
For example:
https://res.cloudinary.com/demo/image/upload/users/avatar.jpg or
https://my-bucket.s3.amazonaws.com/products/image.png or
/admin/files/users-8d91abf.png The entity stores only the URLβnot the file contents.
Updating Files
Updating an existing file is handled automatically.
Instead of manually deleting the previous asset, providers implement an update() operation.
Current File
β
βΌ
Delete Old Asset
β
βΌ
Upload Replacement
β
βΌ
Return New URL The default implementation performs the following:
- Check whether the previous file belongs to the current provider.
- Delete the previous asset.
- Upload the replacement.
- Return the new URL.
Applications rarely need to implement this logic manually.
Deleting Files
When an entity is deleted or a file is replaced, KraftAdmin delegates cleanup to the storage provider.
Delete Entity
β
AdminStorageProvider.delete()
β
Storage Platform
β
Asset Removed Each provider knows how to locate and remove its own assets.
File Ownership
Every provider implements a contains() function.
fun contains(fileUrl: String): Boolean This method determines whether a particular URL belongs to that provider.
For example:
| URL | Provider |
|---|---|
/admin/files/avatar.png | Local Storage |
https://bucket.s3.amazonaws.com/... | Amazon S3 |
https://res.cloudinary.com/... | Cloudinary |
This enables safe replacement of files without accidentally deleting assets managed by another provider.
Integration with Form Fields
Storage providers are automatically used by file-based form fields.
These field types include:
- IMAGE
- FILE
- DOCUMENT
- VIDEO
- AUDIO
Example:
@KraftAdminField(
inputType = FormInputType.IMAGE
)
lateinit var avatar: String When an administrator uploads a new image, the configured storage provider receives the file and returns a public URL.
File Validation
Upload validation is configured using the FileConfig annotation.
Typical validation options include:
- Allowed file extensions
- Allowed MIME types
- Maximum file size
- Minimum file size
- Multiple uploads
- Maximum number of files
Example:
@KraftAdminField(
inputType = FormInputType.IMAGE,
fileConfig = FileConfig(
maxSizeBytes = 5 * 1024 * 1024,
allowedExtensions = [
FileExtension.JPG,
FileExtension.PNG
]
)
) See the File Configuration guide for all available options.
Local vs Cloud Storage
Local Storage
Ideal for:
- Local development
- Small deployments
- Internal applications
- Rapid prototyping
Advantages:
- No external dependencies
- Works immediately
- Fast uploads
- Simple configuration
Cloud Storage
Recommended for:
- Production deployments
- Large files
- Multiple application servers
- High availability
- CDN integration
Advantages:
- Scalable
- Durable
- Globally accessible
- Optimized for media delivery
Storage Independence
One of the design goals of KraftAdmin is provider independence.
Your entities never need to know where files are stored.
Changing storage providers does not require changing entity definitions.
For example, the following field works with every supported storage provider:
@KraftAdminField(
inputType = FormInputType.IMAGE
)
lateinit var profilePhoto: String Whether the application stores files locally, on Amazon S3, or on Cloudinary is completely transparent to the entity.
Custom Storage Providers
If your organization uses another storage platform, implement the AdminStorageProvider interface.
Examples include:
- Google Cloud Storage
- Azure Blob Storage
- MinIO
- DigitalOcean Spaces
- Wasabi
- Backblaze B2
- Company internal storage
- FTP servers
- Network Attached Storage (NAS)
Once registered, KraftAdmin treats custom providers exactly like the built-in implementations.
Best Practices
- Use Local Storage during development.
- Use cloud storage in production.
- Organize uploads using meaningful context folders.
- Configure file validation using
FileConfig. - Store only public URLs inside entities.
- Avoid exposing filesystem paths directly.
Next Steps
- Configure Local Storage
- Configure Amazon S3
- Configure Cloudinary
- Configure File Validation
- Implement a Custom Storage Provider