mattmy / laravel-file-magic
Securely accept, validate, store, query, download, and delete files through one fluent Laravel API.
Requires
- php: ^8.3
- ext-fileinfo: *
- guzzlehttp/psr7: ^2.7
- illuminate/console: ^12.0|^13.0
- illuminate/contracts: ^12.0|^13.0
- illuminate/database: ^12.0|^13.0
- illuminate/filesystem: ^12.0|^13.0
- illuminate/http: ^12.0|^13.0
- illuminate/support: ^12.0|^13.0
- psr/http-message: ^1.1|^2.0
- symfony/http-foundation: ^7.0|^8.0
- symfony/mime: ^7.0|^8.0
Requires (Dev)
- intervention/image: ^4.0
- larastan/larastan: ^3.0
- laravel/pint: ^1.29
- orchestra/testbench: ^10.0|^11.0
- pestphp/pest: ^3.0|^4.0
- pestphp/pest-plugin-laravel: ^3.0|^4.0
Suggests
- ext-curl: Required only when importing files from HTTP(S) URLs.
- ext-zip: Required only when creating ZIP downloads.
- intervention/image: Required only when using image resizing and encoding.
Conflicts
- intervention/image: <4.0
README
Manage files in Laravel through one clear API. FileMagic stores file records with Eloquent and works with Laravel Filesystem disks, so you can upload, find, read, download, and delete files without building the same workflow for every source.
What you can do
- Store uploaded files, local files, content, Base64, and remote HTTP(S) files.
- Generate and store TXT, JSON, and CSV documents.
- Choose the disk, directory, filename, visibility, and collision behavior for each file.
- Limit file size and allow or block MIME types.
- Attach metadata and associate files with Eloquent models.
- Resize supported images before storage.
- Find files by ID, UUID, model, array, or Laravel Collection.
- Read file contents, open streams, create URLs, and return downloads.
- Download multiple files as ZIP or delete files in batches.
- Audit database records whose physical files are missing.
Requirements
- PHP 8.3 or later
- Laravel 12 or 13
- PHP
ext-fileinfo - A configured Laravel Filesystem disk
Remote files need PHP ext-curl. Image resizing needs Intervention Image 4 with GD or
Imagick. ZIP downloads need PHP ext-zip.
Installation
composer require mattmy/laravel-file-magic php artisan vendor:publish --tag=file-magic-config php artisan vendor:publish --tag=file-magic-migrations php artisan migrate
Quick start
use Mattmy\FileMagic\Facades\FileMagic; $file = FileMagic::fromUpload($request->file('document')) ->onDisk('local') ->inDirectory('documents') ->named('contract') ->store(); return FileMagic::find($file)->download();
Store files from different sources
FileMagic::fromUpload($uploadedFile)->store(); FileMagic::fromPath($trustedPath)->store(); FileMagic::fromContent($contents, 'report.pdf')->store(); FileMagic::fromBase64($base64, 'avatar.png')->store(); FileMagic::fromUrl('https://example.com/manual.pdf')->store();
Generate documents with the same storage options:
FileMagic::text('Hello')->named('message')->store(); FileMagic::json(['status' => 'ready'])->named('status')->store(); FileMagic::csv($rows)->named('report')->store();
Configure a file
use Mattmy\FileMagic\Enums\CollisionPolicy; use Mattmy\FileMagic\Enums\FileVisibility; $file = FileMagic::fromUpload($uploadedFile) ->onDisk('s3') ->inDirectory('accounts/42/contracts') ->named('signed-contract') ->visibility(FileVisibility::Private) ->onCollision(CollisionPolicy::Unique) ->maxSize(10 * 1024 * 1024) ->allowMimeTypes(['application/pdf']) ->withMetadata(['category' => 'contract']) ->ownedBy($user) ->store();
Use resizeImage() when supported images should be reduced before storage:
$image = FileMagic::fromUpload($uploadedImage) ->resizeImage(maxWidth: 1200, quality: 80) ->store();
Find and use stored files
$file = FileMagic::find($uuid)->one(); $files = FileMagic::find([$firstId, $secondUuid])->get(); $exists = FileMagic::find($uuid)->exists(); $url = FileMagic::find($uuid)->url(); $temporaryUrl = FileMagic::find($uuid)->temporaryUrl(); $customTemporaryUrl = FileMagic::find($uuid)->temporaryUrl(now()->addMinutes(15)); $contents = FileMagic::find($uuid)->contents(); $stream = FileMagic::find($uuid)->readStream(); return FileMagic::find($uuid)->download();
Use readStream() instead of contents() for large files, and close the returned stream
when finished.
Safety and resource limits
Package configuration is validated strictly. Base64 inputs are rejected from their decoded size before decoding, then decoded in bounded chunks into a temporary stream: the encoded input remains in memory, while decoded bytes use temporary disk space. Storage paths must already be canonical, and image size and MIME policies are checked before and after image processing.
ZIP downloads and deletion
return FileMagic::find($targets)->downloadZip('documents');
$deleted = FileMagic::find($targets)->delete();
Applications must authorize every file before reading, downloading, or deleting it.
Consistency audits
Check whether database records still have matching files on storage:
php artisan file-magic:audit
The command is read-only unless --delete-missing-records is supplied. Remote disks may
add network time and storage request charges, so review the audit guide before scheduling
cleanup.
Handle errors
All package exceptions extend FileMagicException:
use Mattmy\FileMagic\Exceptions\FileMagicException; try { $file = FileMagic::fromUpload($uploadedFile)->store(); } catch (FileMagicException $exception) { report($exception); }
Documentation
For every method, field, parameter, exception, configuration option, performance note, and security recommendation, see the FileMagic documentation.
Report vulnerabilities privately according to SECURITY.md.
License
FileMagic is open-source software licensed under the MIT License.