haruncpi/laravel-simple-filemanager
Laravel Simple File Manager adds a lightweight file manager UI to Laravel apps, letting you browse, upload, rename, delete, and organize files and folders through an easy-to-integrate interface with configurable storage and permissions.
Install the package
composer require haruncpi/laravel-simple-filemanager
Laravel 8+ auto-discovers the service provider; if you're on an older version, register Haruncpi\LaravelSimpleFilemanager\SimpleFilemanagerServiceProvider manually.
Publish everything in one shot
php artisan vendor:publish --provider="Haruncpi\LaravelSimpleFilemanager\SimpleFilemanagerServiceProvider"
php artisan migrate
This typically drops a config/simple-filemanager.php, a migration for the file metadata table, and (depending on version) Blade views/CSS/JS assets.
Check the config first
Open config/simple-filemanager.php. The keys you care about on day one are:
disk — usually public. Anything you upload should be servable via asset() or Storage::url().middleware — defaults to ['web']. Add 'auth' before you do anything else (see Gotchas).route_prefix / prefix — what URL the UI lives under (commonly /filemanager).allowed_extensions / max_size knobs.Create the storage symlink
php artisan storage:link
Without this, uploaded files land on disk but thumbnails and download links 404.
First use case
Visit https://your-app.test/filemanager (or whatever route_prefix you set). You should see the file browser with upload, create-folder, rename, and delete actions. Upload one file, confirm it appears in storage/app/public/<configured folder> and that a row was written to the filemanager table. If either half is missing, the UI is broken — that's your first diagnostic split.
Where to look when something's off: config/simple-filemanager.php → the published migration (for table/column names) → routes/web.php if the package publishes routes → vendor/haruncpi/laravel-simple-filemanager/src/ for the actual controller behaviour. With ~100 stars and thin docs, reading src/ is part of the normal workflow, not a last resort.
The intended pattern is: gate the UI behind auth and use it as the "media" section of an admin panel.
// config/simple-filemanager.php
'middleware' => ['web', 'auth', 'can:manage-files'],
'route_prefix' => 'admin/media',
Then link to route('...') or hardcode url(config('simple-filemanager.route_prefix')) from your admin nav. This is the lowest-friction integration and usually the only one you need.
The package persists file records. Rather than scanning the disk when you need a list of assets, query the model/table it writes to — that gives you names, paths, and timestamps in one place:
$images = DB::table('filemanager') // confirm table name from the migration
->where('path', 'like', 'products/%')
->latest()
->get();
Use this to build pickers, galleries, or to resolve a stored image_path back to a public URL.
When a user picks a file from the manager, save the relative disk path (e.g. products/hero.jpg) on your model and resolve the URL at render time:
public function getImageUrlAttribute(): ?string
{
return $this->image_path ? Storage::disk('public')->url($this->image_path) : null;
}
This keeps you portable if you later switch the manager's disk to S3 or move to a CDN.
The UI is server-rendered with route-driven actions, so the pragmatic integration is a modal or iframe pointed at the filemanager URL, with a small script that posts the chosen path back via window.parent.postMessage or an opener callback. Don't try to import the package's JS as a module — it isn't built as a headless library. If you need a fully headless picker, hit the list endpoint (if exposed) with fetch and render your own grid.
Keep one code path for files: if the UI writes to storage/app/public/<folder>, have your own $request->file('x')->store('folder', 'public') calls write there too. Mixing disks (e.g. UI on public, app on local) is the most common source of "the file exists but I can't see it in the manager."
If you need separate areas (e.g. products/, blog/, avatars/), the simplest approach is one manager instance plus a directory convention enforced by your own forms, rather than trying to reconfigure the package per context. The config is app-global; per-request overrides via config([...]) before the route runs are fragile because the package reads config at boot.
web. On a public-facing app that means anyone can browse, upload, and delete. Add auth (and ideally a policy/ability) to middleware before you deploy, and verify by hitting the URL in an incognito window.storage:link is mandatory. The package uploads into the storage disk, not public/. If thumbnails 404 but files clearly exist, it's almost always the missing symlink or a FILESYSTEM_DISK/disk config mismatch.php artisan config:clear. If you changed middleware and nothing happened, you're looking at a cached config.upload_max_filesize / post_max_size in php.ini or nginx client_max_body_size. Laravel validation errors won't fire if PHP rejects the request before it reaches the app.src/, and if needed wrap or replace the upload route with your own mimes: / max: validated handler./filemanager or the default prefix clashes with a resource route, change route_prefix early — renaming later means updating every link and any saved iframe/modal URLs.composer update doesn't silently clobber expectations.files or filemanager table will fail the migrate. You can edit the published migration before running it.vendor/haruncpi/laravel-simple-filemanager/src/ for anything beyond the happy path — especially the list endpoint's JSON shape if you're building a custom picker, and the exact delete/rename request parameters.storage/app/public/<folder>? (3) is the DB row written? (4) does Storage::disk('public')->url($path) return a working URL? Whichever step fails tells you whether it's a routing, filesystem, database, or symlink problem — and those are the only four failure classes this package really has.disk at S3, verify that thumbnails and previews render, because the UI may build URLs locally.How can I help you explore Laravel packages today?