mattmy / laravel-file-magic
A strongly typed file management package for Laravel.
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
FileMagic is a file-management package built exclusively for Laravel. It provides one consistent workflow for accepting, validating, storing, querying, downloading, and deleting files through Laravel Filesystem and Eloquent.
Requirements
- PHP 8.3 or later
- Laravel 12 or 13
- PHP
ext-fileinfo - A configured Laravel Filesystem disk
Composer checks ext-fileinfo during installation because FileMagic detects
MIME types from actual file contents instead of trusting filenames or
client-provided MIME types.
Remote HTTP(S) imports through fromUrl() additionally need PHP ext-curl.
Without it, all other features remain available, while storing a remote source
throws RemoteDownloadUnavailable. Image resizing additionally needs
intervention/image 4.0 or later and GD or Imagick. ZIP downloads additionally
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
Store an uploaded file:
use Mattmy\FileMagic\Facades\FileMagic; $file = FileMagic::fromUpload($uploadedFile) ->onDisk('local') ->inDirectory('documents') ->named('contract') ->store();
Retrieve it by ID, UUID, model, array, or Laravel Collection:
$file = FileMagic::find($uuid)->one(); return FileMagic::find($file)->download();
The same PendingFile workflow supports local paths, content, Base64, remote
HTTP(S) files, and generated TXT, JSON, and CSV documents:
$document = FileMagic::json([ 'message' => 'Hello', ]) ->onDisk('s3') ->inDirectory('exports') ->named('message') ->store();
Highlights
- Strict content inspection, size limits, MIME allowlists, and safe path handling
- Streaming storage, reads, downloads, and bounded ZIP creation
- SSRF-resistant URL imports with TLS verification enabled by default
- Best-effort image resizing with Intervention Image 4
- Collision policies with recovery for failed overwrite operations
- Ordered batch lookup, consistency-aware batch deletion, and storage audits
- Custom stored-file model and table support
- English and Traditional Chinese documentation
Overwrite creates a complete backup on the PHP server's local temporary disk
before replacing an object. It uses additional disk space and I/O, so it is
slower than normal storage; prefer the default Unique policy unless the same
storage path must be preserved.
Documentation
The complete guide, configuration reference, security notes, examples, and troubleshooting information are available at:
Read the FileMagic documentation
- Getting started
- Storing files
- Remote files
- Documents and images
- Querying files
- ZIP and deletion
- Consistency audits
- Models and exceptions
- API reference and troubleshooting
Consistency audits
php artisan file-magic:audit checks whether every database record still has
its disk + path object. It is read-only by default. Each record causes one
filesystem exists() call; remote disks such as S3 can therefore add execution
time and request charges. --chunk limits database memory, not storage requests.
The command never lists storage or deletes physical objects.
Cleanup requires --delete-missing-records and confirmation, or --force in
non-interactive environments. Cleanup uses one bulk database delete per chunk,
does not dispatch per-model Eloquent events, and is not one transaction: if a
later chunk fails, earlier chunks may already be deleted. Storage or network
errors are treated as unknown and never as proof that an object is missing.
Read the audit guide
before enabling cleanup or scheduling the command.
Security
Applications must authorize every file operation and retain Laravel request validation at the HTTP boundary. Treat original filenames, client MIME values, remote content, and stored bytes as untrusted. See the security guide before accepting untrusted files or URLs.
Report vulnerabilities privately according to SECURITY.md.
Consistency audits
php artisan file-magic:audit checks whether every database record still has
its disk + path object. It is read-only by default. Each record causes one
filesystem exists() call; remote disks such as S3 can therefore add execution
time and request charges. --chunk limits database memory, not storage requests.
Cleanup requires --delete-missing-records and confirmation, or --force in
non-interactive environments. Cleanup uses one bulk database delete per chunk,
does not dispatch per-model Eloquent events, and is not one transaction: if a
later chunk fails, earlier chunks may already be deleted. Storage or network
errors are treated as unknown and never as proof that an object is missing.
Read the audit guide
before enabling cleanup or scheduling the command.
License
FileMagic is open-source software licensed under the MIT License.
Read CONTRIBUTING.md before submitting a pull request. Releases follow Semantic Versioning and are documented in CHANGELOG.md.