backpack/filemanager
File manager for Backpack for Laravel: browse, upload, rename, crop, and delete files and folders right from your admin panel. Powered by elFinder, it supports multiple disks, image editing, and reusable upload fields.
backpack/filemanager is an addon for Backpack for Laravel — it does not work standalone. It packages the elFinder file browser behind Backpack's admin middleware and exposes it as (a) a full-page media manager and (b) a form field type you can drop into CRUD panels.
Minimal path from zero to first use:
composer require backpack/filemanager
php artisan vendor:publish --provider="Backpack\FileManager\FileManagerServiceProvider"
Check config/backpack/ (and config/elfinder.php on older versions) — the disks array is the file that actually matters.'disks' => ['public'], and make sure the disk is reachable:
php artisan storage:link
resources/views/vendor/backpack/base/inc/sidebar_content.blade.php:
<li class="nav-item"><a class="nav-link" href="{{ backpack_url('file-manager') }}">
<i class="nav-icon la la-files-o"></i> <span>File Manager</span></a></li>
backpack_url('file-manager') while logged in as an admin.Where to look first: the published config file (disks, roots, elFinder options) and vendor/backpack/filemanager/src/ — the controller is thin, so most behaviour lives in the config and the elFinder connector.
First use case: a Post CRUD with a cover image. Add a field of type elfinder, upload an image through the File Manager page, then pick it from the field's browse modal and store the relative path.
CRUD field pattern (the thing you'll do most). The field renders an elFinder browser and writes a relative path into your column:
$this->crud->addField([
'name' => 'cover_image',
'label' => 'Cover image',
'type' => 'elfinder',
// 'filter' => 'image', // restrict to images
]);
Because the field stores a path, pair it with an accessor on the model so views never touch the disk directly:
public function getCoverImageUrlAttribute(): ?string
{
return $this->cover_image
? Storage::disk('public')->url($this->cover_image)
: null;
}
Multi-root / multi-disk setups. The config's disks array becomes one elFinder root per disk. Use this to separate public marketing assets from private documents, then add per-root attributes (read-only, locked, hidden) in the elFinder roots options. A read-only "Brand assets" root plus a writable "Uploads" root is a common pattern.
WYSIWYG integration. The same elFinder can back CKEditor/Summernote/TinyMCE by pointing the editor's file-browser URLs at backpack_url('file-manager') with the appropriate ?callback= / ?field= parameters the editor expects. This gives editors one shared media library instead of a separate upload widget per field.
Permission gating. The route sits in Backpack's admin middleware group, so only admins get in — but if you use Backpack's PermissionManager you usually want a dedicated permission. Add a check to the route/middleware group so "can access file manager" is a role you can grant, and mirror the same check in the sidebar @can so the menu item disappears for non-admins.
Restricting destructive commands. For non-technical admins, strip capabilities in the elFinder options rather than trusting training:
'disabled' => ['mkfile', 'write', 'archive', 'extract', 'chmod'],
Keep mkfile/write only if you actually want in-browser text editing — it is a live code path on your server.
Menu + route customisation. Change the URL via the published route config, then update every backpack_url('file-manager') reference (menu, WYSIWYG config, editor settings). Grep before shipping.
Storage::disk(...)->url() in an accessor, never concatenate /storage/ in Blade.disk:path and split it) before writing to the column, or your URLs break the day you add a second disk.storage:link and filesystem permissions. Uploads silently fail if public/storage is missing or storage/app/public isn't writable by the web user. Test an upload immediately after install — do not discover this in production.upload_max_filesize, post_max_size, and elFinder's own uploadMaxSize option. Raising one and not the others gives you a confusing "upload failed" with no server error.php artisan config:clear (or config:cache). Symptom: your new disk/option "doesn't exist".backpack_url('file-manager/connector') in a tab to see the raw JSON error, and tail storage/logs/laravel.log..tmb thumbnails inside the root by default. That directory will pollute your uploads and may need to be gitignored/cleaned; it can also break on read-only roots — point the tmbPath at a writable location.php artisan backpack:check style diagnostics and the browser console.'s3' to disks alone will not work. Budget time or keep remote storage on a local-temp sync.NOASSERTION licence has a small maintenance surface. Read the LICENSE file rather than assuming MIT, and keep it out of any legal-review-critical path until cleared.roots, disabled, disks) — forks of the connector tend to rot on upgrade.storage/app/public with the symlink; if you must use public/uploads, gitignore it explicitly so a deploy doesn't overwrite user files.How can I help you explore Laravel packages today?