Skip to main content

Introduction

note

This guide assumes familiarity with the Spring Framework.
If you are new to Spring, we recommend starting with their official guides to get up to speed.

Singularity provides a robust and pluggable file storage system for managing file uploads and their metadata. It's designed to handle different storage backends and ensure data consistency between the database and the actual stored files.

Limiting File Size

There is no direct, efficient way to limit file size for uploads within the application's reactive stream processing. Due to the purely reactive nature of Singularity, the real size of a file can only be determined after loading the entire content into memory completely. Attempting to check the size mid-stream requires buffering, which negates the non-blocking benefit.

Therefore, it is highly recommended to set a file size limit in your front-facing server configuration (e.g., Nginx, Traefik, or Cloud Load Balancer).

For example, in Nginx, you would use:

client_max_body_size 10M;

This prevents large requests from ever reaching the reactive application, preserving backend performance.

Core Concepts

FileStorage

This is an abstract class that defines the core logic for managing files, including upload, exists, and remove operations. It provides a consistent interface for different storage implementations (e.g., S3, local). It also includes a consistency check to ensure the file's metadata in the database matches the actual file in storage.

FileMetadataDocument

This is the core data model for file metadata. It stores a unique ID, a developer-friendly key, a unique ID, a content type, file size, and access details. The FileMetadataDocument is stored in a MongoDB collection.

Key Operations

upload

This method handles the file upload process. It takes the user's ID, the file part, a unique key, and a public flag. It generates a unique file name, uploads the file to the configured storage backend, and saves its metadata to the database.

exists

This method checks for a file's existence by verifying both the database record and the file in storage. It includes a consistency check: if a file exists in one place but not the other, it will be removed from both to maintain data integrity.

remove

This method deletes a file and its associated metadata. It removes the file from the storage backend and then deletes the FileMetadataDocument from the database.

metadataResponseByKey

This method retrieves a FileMetadataDocument by its key and converts it into a FileMetadataResponse, which includes a URL to access the file.

File Key

FileKeys help you to create a unique key to identify your files.

A FileKey can be created based on

  • aprefix (e.g. user/123456),
  • a filename (e.g. avatar),
  • a suffix (e.g. small) and
  • an extension (e.g. jpeg).

A UUID will be attached to make the key unique to prevent cache busting.

val fileKey = FileKey(
prefix = "user/123456",
filename = "avatar",
suffix = "small",
extension = "jpeg"
)

This will result in /user/123456/avatar_small-3bb2c18c-xxx.jpeg.

Renditions

It is possible to store multiple renditions of a file, e.g. a compressed version and the original. The image store automatically creates a small, medium and large rendition of the image. If only one rendition is stored, it will be stored as original.

warning

It is important to distinguish rendition keys with the key of file metadata.

  • The key of the file metadata is a content key which is used to control access for example. (You can learn more here).
  • The key of a rendition is a file storage key. The file will be identified by this key.

One rendition: If the file is uploaded through upload, both keys will be the same.

Multiple renditions: If multiple renditions are uploaded through uploadMultipleRenditions, it is only possible to delete the whole collection through the key that you specified in the upload. You can only access the renditions through the file metadata.

Configuration

PropertyTypeDescriptionDefault value
singularity.file.storage.typeLOCAL or S3The implementation of the file storage. The available options are S3 and LOCAL. Check out the respective documentation for more configuration options.true