File Storage
Introduction
D reamFork provides a filesystem to facilitate working with files. This filesystem leverages the Symfony Filesystem component for enhanced file management capabilities.
Configuration
DreamFork's filesystem configuration file is located at /config/storage.php. In this file, you can define disks for the filesystem. All disks utilize files stored locally on the server running the DreamFork application. For each disk, you can define four options:
-
root: Indicates the absolute path to the directory -
url: Specifies the public address of the directory through a symbolic link (optional). -
log_exceptions: Specifies whether the filesystem should log exceptions encountered while working with files (optional, false by default). -
throw: Specifies whether exceptions encountered during file operations should be thrown (optional, false by default).
You may configure as many disks as you like.
The Local Disk
The local disk points to the /storage/app folder. It can be utilized when you want to store files that shouldn't be publicly accessible. For example, if your application generates documents based on a user-filled form, you may choose to save these files on the local disk. Access to the public disk can also be obtained from the local disk.
use Framework\Support\Facades\Storage;
Storage::disk('local')->put('document.txt', 'Some content');
The Public Disk
The public disk points to the /storage/app/public folder, which is a directory that can be symbolically linked for public access, such as from a web browser. It is recommended to use this disk when working with files intended for public access.
use Framework\Support\Facades\Storage;
Storage::disk('public')->saveFile($file, $sourcePath, $filename);
By default, the public disk's
urloption points to the "/storage" path. If you have created a symbolic link with a custom name, you need to specify that name in the storage configuration file for theurloption.
The Log Disk
The log disk points to the /storage/logs folder and is used by the framework for generating logs. If you wish to create your own event logs, you can utilize this disk.
Creating Custom Disk
Creating custom disks is straightforward. You only need to define a new entry in your configuration file and set the appropriate options. For example, let's say you frequently store images in a specific folder in your application. You can define a disk for this folder to avoid the need to specify the folder each time you use one of the default disks:
'disks' => [
// ...
uploads' => [
'root' => storage_path('app/public/uploads'),
'url' => env('APP_URL').'/storage/uploads',
],
];
Working With Filesystem
Obtaining Disk Instances
The Storage facade can be utilized to interact with any of the configured disks. For instance, you can use the files method on the 'local' disk to list files from that directory. If you call the disk() method without any arguments, the default disk defined in the configuration will be used.
use Framework\Support\Facades\Storage;
Storage::disk()->files(); // disk => 'local'
Retrieving Files
The get method can be used to retrieve the contents of the specified file. If the file is not existing, null will be returned.
Storage::disk('public')->get('data.txt');
The exists method can be used to check whether a specific file or directory exists on the disk.
if (Storage::disk('public')->exists('image.png')) {
// ...
}
The files method facilitates listing files. You can provide the directory you want to list as the first argument; by default, it is the root directory of the specified disk. The second argument is optional and allows you to specify whether to list hidden files.
$files = Storage::disk('public')->files();
$filesWithHidden = Storage::disk('public')->files('', true);
The files method, however, does not perform a deep search; it only returns files directly within the specified folder. To list all files in a given folder, you should use the allFiles method. It accepts the same arguments as files.
$allFiles = Storage::disk('public')->allFiles('', true);
The directories method can be used list directories in a specified folder. You can provide the name of the folder as the first argument; by default, it is the root folder for the specified disk.
$directories = Storage::disk('public')->directories();
The fileSize method retrieves the size of a file in bytes while the formattedFileSize method retrieves the size of a file in a human-readable format (e.g., "2.50MB").
$fileSize = Storage::disk('public')->fileSize('image.png');
$formattedFileSize = Storage::disk('public')->formattedFileSize('image.png');
The dirSize method retrieves the size of a directory in bytes while the formattedDirSize method retrieves the size of a directory in a human-readable format (e.g., "2.50MB").
$dirSize = Storage::disk('public')->dirSize('image.png');
$formattedDirSize = Storage::disk('public')->formattedDirSize('image.png');
The lastModified method retrieves the last modified timestamp of a file or directory.
$lastModifiedFile = Storage::disk('public')->lastModified('image.png');
$lastModifiedDir = Storage::disk('public')->lastModified('images');
File URLs
You can use the url method to obtain a URL for a specific file. This method utilizes the url option from the disk configuration and should only be used for the public disk.
$url = Storage::disk('public')->url('image.png');
When using this method, keep in mind that to make the obtained URL accessible, you need to create a symbolic link for the public folder beforehand.
URL Host Customization
If you would like to change the host for URLs generated using the Storage facade, you may edit a url option to the disk's configuration array:
'public' => [
// ...
'url' => env('APP_URL').'/custom'
]
Storing Files
The put method can be used to store file contents on a disk. Remember, all file paths should be specified relative to the "root" location configured for the disk:
Storage::disk('public')->put('file.jpg', $contents);
If the put method (or other "write" operations) is unable to write the file to disk, false will be returned. If you wish, you may define the throw option within your filesystem disk's configuration array. When this option is defined as true, unsuccessful filesystem operations will throw the appropriate exception.
'public' => [
// ...
'throw' => true
]
The makeDirectory method allows you to create a directory or directories. The first argument is the path to create, the second optional argument is the permissions for the folder, and the third is whether to create parent directories if they do not exist.
Storage::disk('public')->makeDirectory('images/avatars');
The storeTextFile method stores the content in a text file at the specified path. It accepts two arguments: the path for the text file and the content to be written to the file.
Storage::disk('public')->storeTextFile('files/data', 'content');
The writeTextFile method writes content to a text file at the specified path, optionally appending to an existing file. It requires two mandatory arguments, similar to storeTextFile, and two optional arguments: whether the text should be appended at the beginning or end of the file (default is false for the end of the file), and whether a newline character should be added (default is true).
Storage::disk('public')->writeTextFile('files/data', 'more content at beginning', true, true);
The saveFile method saves an uploaded file to the specified directory with the specified filename, optionally overwriting an existing file. It requires three mandatory arguments: the file to be saved, the path for the file, the filename, and one optional argument whether it should overwrite a potentially existing file (default is false).
Storage::disk('public')->saveFile($file, $path, $filename);
Copying & Moving Files
The copy method may be used to copy an existing file to a new location on the disk, while the move method may be used to rename or move an existing file to a new location. Additionally, you can use the rename method, which is essentially an alias for the move method.
Storage::disk('public')->copy('original.jpg', 'copied.jpg');
Storage::disk('public')->move('old.jpg', 'new.jpg');
Storage::disk('public')->rename('old.jpg', 'new.jpg');
Uploading Files
In your application, you may need to save files uploaded by users. To achieve this, you can use one of the previously described functions, such as saveFile().
Storage::disk('public')->saveFile($request->files->get('attachment'), 'uploads', 'image.png');
Keep in mind that the folder provided for saving the file must already exist, as
saveFiledoes not create it in case it is missing.
Deleting Files
The remove method takes a single argument, which is the name of the individual file or directory to be deleted. You can also use the delete method, which is an alias for remove.
Storage::disk('public')->remove('uploads/image.png');
Keep in mind that this method deletes the specified file or directory unconditionally. Therefore, if you specify a folder for deletion that contains other folders and files, it will be removed without warning, along with its entire contents.
Disk Scopes
The Dreamfork filesystem appropriately secures executed operations in terms of scope access. This means that performing operations on an object outside the path defined as the root for a specific disk is not possible. Let's illustrate this with the following example:
Storage::disk('public')->allFiles('../');
Such an operation will fail or throw an exception when the throw option is enabled in the configuration. This is because using '../' attempts to access content beyond the disk's scope. Given that the 'public' disk has its root path directed to /storage/app/public, using '../' would navigate to storage/app, which is disallowed due to being outside the disk's scope.