escolalms/files
File management package for the EscolaLMS Laravel platform, providing upload, storage, and retrieval of files and media attached to courses and other LMS entities, with configurable storage drivers and integration into the wider EscolaLMS ecosystem.
This release (0.1.29) is a small but practical one: xlsx and zip are now accepted file types. If you were previously working around the package by base64-ing spreadsheets or storing archives outside the file table, that workaround can go away.
Minimal setup:
composer require escolalms/filesphp artisan vendor:publish --provider="EscolaLMS\Files\Providers\FilesServiceProvider"
php artisan migrate
config/files.php (or the package's config file name after publishing) for the allowed MIME/extension list, max upload size, and the storage disk. Confirm xlsx and zip are present after upgrading — if you have a published config from an older version, the config file is not re-published automatically, so you must merge the new entries yourself.php artisan route:list --path=files to see the registered upload/download endpoints and their middleware.Where to look first, in order: the config file (whitelist + disk), the File model and its relationships, the upload controller/request (to see how validation is actually applied), then the routes file.
First use case: upload a spreadsheet through the package endpoint, receive the file record/ID, and attach it to your domain model (e.g. an import job or a course resource) rather than handling UploadedFile yourself. That keeps disk configuration, naming, and cleanup consistent across the app.
Upload-then-attach. Use the package endpoint to persist the file, then store the returned file identifier on your own model. This keeps you from re-implementing disk logic and means the package's cleanup/authorization rules apply uniformly. Wrap it in a FormRequest of your own so validation messages match the rest of your API.
Layered validation for the new types.
xlsx: validate with mimes:xlsx and mimetypes:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet where possible. An xlsx is a ZIP container internally, so sniffing can legitimately report application/zip.zip: validate extension plus a size cap; there is no reliable content check beyond "is a valid archive".Processing belongs in a job. For zip archives, do not extract inline in the request. Dispatch a queued job with ZipArchive, cap the number of entries and total uncompressed size, and write to a temp directory you clean up. For xlsx, queue the read (Laravel Excel / PhpSpreadsheet) and report results back through your normal notification channel.
Disk strategy. Keep one canonical disk for uploaded files and derive URLs from it. If you serve zip downloads, prefer streamed responses over loading into memory, and use temporary/signed URLs rather than exposing the storage path.
Testing. Use Storage::fake() and UploadedFile::fake()->create('import.xlsx', 100, 'application/vnd...sheet'). Fake files with a real MIME type are the only way to catch the xlsx/zip sniffing ambiguity in CI rather than in production.
.xlsx because your published whitelist predates the release. Diff the package config against yours on every upgrade.mimetypes rule can let one through as the other. Decide explicitly whether you accept application/zip and, if so, only where archives are genuinely expected (e.g. a separate imports endpoint), not on avatar uploads.upload_max_filesize and post_max_size silently truncate or reject before your validation runs. A zip that fails with an empty request body is almost always this, not the package..., and enforce an uncompressed-size ceiling.public, php artisan storage:link is a prerequisite that is easy to forget in fresh environments.^0.1.29 and read the diff between patch releases; at 0.1.x, "support for xlsx and zip" arriving in a patch is normal, so treat each bump as potentially behavior-changing for validation.How can I help you explore Laravel packages today?