File API internals
The goals of the File API are to:
- allow files to be stored within Moodle, as part of the content
- use a consistent and flexible approach for all file handling throughout Moodle
- give components control over which users can access a file, using capabilities and other local rules
- make it easy to determine which parts of Moodle use which files, to simplify operations like backup and restore
- track where files originally came from
- avoid redundant storage, when the same file is used twice
- fully support Unicode file names, irrespective of the capabilities of the underlying file system
- support alternative file systems, including cloud-based APIs
Overview
The File API is a set of core interfaces to allow the rest of Moodle to store, serve, and manage files. It applies to all files that are part of the Moodle site's content. It is not used for internal files, such as those in the following subdirectories:
dataroot
temp
lang
cache
environment
filter
search
sessions
upgradelogs
See the File API documentation for information on using the File API.
The API can be subdivided into the following parts:
- File system - Low level storage of file content, without access control
- File storage - Storage of file metadata
- File serving - Handle the retrieval and serving of files from the File storage API, including:
- serving the files on request
- performing appropriate access checks
- File related user interfaces - Provides the interface for uploading files, including:
- Form elements allowing users to select a file using the file picker, and have it stored within Moodle.
- UI for users to manage their files, replacing the old course files UI
- File browsing API - Allow code to browse and optionally manipulate the file areas, including:
- find information about available files in each area
- print links to files
- optionally move, rename, copy, delete, and perform other user-facing operations.
File API internals
File System
The File System API allows for files to be stored in alternative underlying file systems, for example in an cloud-based API such as Amazon S3. Each file is stored and retrieved using a contenthash
.
The file content hash is calculated by taking a SHA1 hash of the content of the file. This should be unique enough so as to allow any number of files to be uploaded to the File API without any natural collisions occurring, and allows the File system to store a single copy of a file, no matter how many times that file content is used within user-generated content.
This means Moodle can not store two files with different content and the same SHA1 hash, luckily it is extremely unlikely that this would ever happen. Technically it is also possible to implement reliable collision tests (with some performance cost), though Moodle currently checks for this case using a simple file length check in addition to SHA1 hash.
The default file system shipped with Moodle stores all files on disk within the moodledata
sub-directory of $CFG->dataroot
.
Suppose a file has a content hash of 081371cb102fa559e81993fddc230c79205232ce
, then it will be stored in on disk as moodledata/filedir/08/13/081371cb102fa559e81993fddc230c79205232ce
.
As files in the standard disk-based file storage API are named using their SHA1 hash, there is a simple way of validating files have not become corrupted using the 'sha1sum' command available in most GNU/Linux distributions.
Where a file is correct then the filename will match the sha1sum
of the file. for example:
$ cd /moodlepath/moodledata/filedir/1d/df/
$ sha1sum 1ddf5b375fcb74929cdd7efda4f47efc61414edf
1ddf5b375fcb74929cdd7efda4f47efc61414edf 1ddf5b375fcb74929cdd7efda4f47efc61414edf
Where a file has become corrupted, these will differ:
$ cd /moodlepath/moodledata/filedir/42/32/
$ sha1sum 42327aac8ce5741f51f42be298fa63686fe81b7a
9442188152c02f65267103d78167d122c87002cd 42327aac8ce5741f51f42be298fa63686fe81b7a
File Storage
The File Storage API is provided by the \file_storage
class, and stores all metadata relating to a file. It interacts with the File System API and the \stored_file
class to provide all low-level storage functionality.
Files table
The File system API stores all file records in the files
database table. This table contains one entry for each usage of a file. Enough information is kept here so that the file can be fully identified and retrieved again if necessary.
If, for example, the same image is used in a user's profile, and a forum post, then there will be two rows in this table, one for each use of the file, and Moodle will treat the two as separate files, even though the file is only stored once on disc.
Entries with a file name of .
represent directories. Directory entries like this are created automatically when a file is added within them.
The name files
is used in the plural form, even though it goes against the coding guidelines because file
is a reserved word in some SQL dialects.
Implementation of basic operations
The low level access API is defined in the \file_storage
class, which can be obtained using the get_file_storage()
function, for example:
$fs = get_file_storage();
Details of common operations are documented in the File System API documentation
File serving
The File serving component of the File API deals with serving files to the user. This is typically in the form of browser requests. Moodle has several main files to handle serving of files. These include:
draftfile.php
- the script used to serve files in a user'sdraft
file area.pluginfile.php
- the script typically used by a plugin to access content.tokenpluginfile.php
- the script typically used by a plugin to access content when a user is not logged in. This is usually in situations where a file is referred to in an e-mail or other similar scenario.
It is the plugins responsibility to handle:
- access control
- optional XSS protection - student submitted files must not be served with normal headers, we have to force download instead; ideally there should be second wwwroot for serving of untrusted files
- links to these files are constructed on the fly from the relative links stored in database (see Generating a URL to your files for further information).
Each plugin should only ever use the File Storage API to access its own files.
File related user interfaces
Files are typically selected by users and uploaded to Moodle using the File manager, and the file picker.
- The file manager is an interface used to view, and delete existing files, and to add new files.
- The file picker is an interface, often accessed using the file manager, to select files for upload to Moodle. The file picker makes use of file repositories.
Form fields
Moodle defines two form field types as part of the formslib
integration, these are:
- The
filepicker
; and - the
filemanager
.