Versions:

File storage

This section describes how the asset store abstraction layer stores the physical files underlying the ORM, and explains some of the considerations.

Component Overview

The assets module is composed of these major storage classes:

These interfaces are also provided to abstract certain behaviour:

Storage via database columns

Asset storage is provided out of the box via a Flysystem backed store. However, any class that implements the AssetStore interface could be substituted to provide storage backends via other mechanisms.

Internally, files are stored as DBFile records on the rows of parent objects. These records are composite fields which contain sufficient information useful to the configured asset backend in order to store, manage, and publish files. By default this composite field behind this field stores the following details:

Field name Description
Hash The sha1 of the file content, useful for versioning (if supported by the backend)
Filename The internal identifier for this file, which may contain a directory path (not including assets). Multiple versions of the same file will have the same filename.
Variant The variant for this file. If a file has multiple derived versions (such as resized files or reformatted documents) then you can point to one of the variants here.

Note that the Hash and Filename always point to the original file, if a Variant is specified. It is up to the storage backend to determine how variants are managed.

Note that the storage backend used will not be automatically synchronised with the database. Only files which are loaded into the backend through the asset API will be available for use within a site.

Public file paths

Public files are published either directly through the "Assets" CMS UI, or indirectly as part of a versioned ownership structure. They are stored as you'd expect on the filesystem: In their folder, by their file name.

assets/
    my-public-folder/
        my-public-file.jpg

The URL for this file will match the physical location on disk: http://www.example.com/assets/my-public-folder/my-public-file.jpg.

Variant file paths (e.g. resized images)

Each file can have variants, most commonly resized versions of an image. These can be generated by resizing an image in the CMS rich text editor, through template logic, or programmatically with PHP. They are stored in the same folder alongside the original file, but contain a special variant suffix.

assets/
    my-public-folder/
        my-public-file.jpg
        my-public-file__FitWzYwLDYwXQ.jpg

The URL for this file will match the physical location on disk: http://www.example.com/assets/my-public-folder/my-public-file__FitWzYwLDYwXQ.jpg.

Note: Before 4.4.0, public files were stored with a content hash by default (see Protected file paths).

Protected file paths

Uploaded files are protected by default, which puts them in a "draft" mode that requires permissions to view them. Protected files can also be published but access restricted. In either case, they're stored in a special assets/.protected folder. In this case, they're stored in a folder matching the truncated hash of the file's content.

assets/
    my-public-folder/
        my-public-file.jpg
        my-public-file__FitWzYwLDYwXQ.jpg
    .protected/
        my-protected-folder/
            b63923d8d4/
                my-protected-file.jpg
                my-protected-file__FitWzYwLDYwXQ.jpg

This corresponds to a file with the following properties:

  • Filename: my-protected-folder/my-protected-file-hash/my-protected-file.jpg
  • Hash: b63923d8d4089c9da16fbcbcdfef3e1b24806334 (trimmed to first 10 chars)
  • Variant: FitWzYwLDYwXQ (corresponds to Fit[60,60])

The URL for this file will not match the physical location on disk. It leaves out the .protected/ folder, and leaves that to SilverStripe's integrated routing: http://www.example.com/assets/my-protected-folder/b63923d8d4/my-protected-file.jpg.

For more information on how protected files are stored see the file security section.

Versioned file paths

Older versions of file contents are kept in the .protected folder, following the same rules as protected file paths.

assets/
    my-file.jpg <- current published file
    .protected/
        dec83f348d/ <- old content hash of replaced file version
            my-file.jpg
        b63923d8d4/ <- old content hash of replaced file version
            my-file.jpg

Versioned and archived files

By default, when files are replaced or removed, their original file contents aren't retained in order to avoid bloat on the filesystem. Changes are only tracked for file metadata (e.g. the Title attribute).

You can opt-in to retaining the file content for replaced or removed files.

SilverStripe\Assets\Flysystem\FlysystemAssetStore:
  keep_archived_assets: true

The filesystem structure follows the same rules as protected file paths:

assets/
    my-file.jpg <- current published file
    .protected/
        dec83f348d/ <- old content hash of replaced file version
            my-file.jpg
        b63923d8d4/ <- old content hash of replaced file version
            my-file.jpg

Loading content into DBFile

A file can be written to the backend from a file which exists on the local filesystem (but not necessarily within the assets folder).

For example, to load a temporary file into a DataObject you could use the below:

use SilverStripe\ORM\DataObject;

class Banner extends DataObject 
{
    private static $db = [
        'Image' => 'DBFile'
    ];
}

// Image could be assigned in other parts of the code using the below
$banner = new Banner();
$banner->Image->setFromLocalFile($tempfile['path'], 'my-folder/my-file.jpg');

Was this article helpful?