Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

File Uploader Bundle Laravel Package

modera/file-uploader-bundle

Modera FileUploaderBundle is a Symfony bundle that handles file uploads within Modera-based applications, providing reusable upload handling for controllers and forms so files can be received, stored, and managed consistently across the Modera ecosystem.

View on GitHub
Deep Wiki
Context7

Getting Started

First, the reality check: modera/file-uploader-bundle is a Symfony bundle, not a Laravel package. It cannot be composer required into a Laravel app and wired up — there is no service provider, no facade, no config publishing. If your project is Laravel, treat this as a design reference for how an upload pipeline was structured circa 2016, not as a dependency. If your project is Symfony (likely 2.x/3.x era), it can be installed, but read the risk section before you commit.

Where to look first (in order):

  1. composer.json — confirm the symfony/* constraints and php requirement. If it caps at symfony/symfony: ~2.8|~3.0, modern Symfony is out and so is PHP 8.
  2. DependencyInjection/ + Resources/config/services.yml — this is where the uploader service, storage path parameter, and any validation hooks are declared. That file is the real documentation.
  3. Resources/config/routing.yml — gives you the actual upload endpoint path. Confirm with bin/console debug:router | grep -i upload.
  4. Controller/ — the entry point that accepts the request and returns the JSON payload. Read this before writing any client code so you know the exact response shape.
  5. Controller/ + Form/ (if present) — tells you whether uploads are "move immediately" or "stage and attach later."

Enable it the old way in app/AppKernel.php:

new Modera\FileUploaderBundle\ModeraFileUploaderBundle(),

Then import routing in app/config/routing.yml and set the storage directory parameter (usually in parameters.yml). Point it at %kernel.root_dir%/../var/uploads — never inside web/.

First use case: stand up the upload endpoint, POST a single file to it with the bundle's expected field name, and inspect the JSON. Once you have the returned identifier/token, persist that string on your own entity — the bundle typically stores the file and hands back a reference; linking it to your domain model is your job, not the bundle's.

Implementation Patterns

Upload-then-attach (the dominant pattern). The upload endpoint stores the file immediately and returns a token. Your form holds that token in a hidden field. On form submit you resolve the token to the stored file and associate it. This decouples the slow part (upload) from the transactional part (save). The cost is orphaned files — see Gotchas.

Stage-and-move. Some versions accept the upload only after the parent entity exists and a form is submitted. This avoids orphans but makes large-file UX worse and forces a full form round-trip. Check the controller for whether the move happens in the upload action or later; don't assume.

Validation lives with you, not the bundle. The 2016-era bundle will do a basic accept and store. Enforce size, MIME (not just extension), and image dimensions in a decorated service or an event subscriber wrapping the upload action. For Laravel ports, that's a FormRequest with mimes: and max: rules — same idea, cleaner home.

Storage is a parameter, so treat it as an extension point. If you need S3/GCS, do not fork the bundle. Decorate the uploader service in your app's services.yml, delegate to the original, and copy the resulting file to your disk. Or write a compiler pass that replaces the storage service ID — but only if the bundle's services are not marked public: false in a way that locks you out. Verify with debug:container <service-id>.

Client side. The bundle predates modern JS tooling and expects a plain multipart POST (jQuery/FormData) to the route from debug:router. Build your frontend against the JSON contract you observed in step 4, and pin that contract in a test — it is undocumented and will not survive a refactor.

Chunking. If large files matter, confirm whether the controller honors Content-Range or a chunk/chunks parameter before promising resumable uploads. Many bundles of this vintage advertise chunking but implement it in a JS plugin only.

Porting to Laravel (the likely path for you): replicate the shape rather than the code.

  • POST /uploads controller → Storage::disk('local')->putFileAs('tmp/'.$token, ...), return {token, name, size}.
  • A temporary_uploads table with token, path, expires_at, plus an artisan command pruning rows older than 24h.
  • A HasUploads trait or explicit attachUpload($token, $collection) service to move from tmp/ to permanent storage on save.
  • Serve private files through a signed-route controller, never a public symlink, unless the assets are genuinely public.

Gotchas and Tips

It is effectively abandoned. Last release 2016-06-10, zero stars, zero dependents. That means no security patches, no PHP 8 compatibility work, and no one to ask when it breaks. If you adopt it: pin the exact version, commit composer.lock, vendor the source if the repo could disappear, and schedule a replacement. Budget the port now rather than after an incident.

It will not install on a modern stack. Expect symfony/symfony constraints around 2.8/3.x and a php: >=5.5 style requirement. composer require on Symfony 6/7 or PHP 8.1+ will fail on constraint resolution or, worse, install and then fatal on deprecated APIs (e.g. getMock, old ContainerAware, AppKernel conventions). Test on a throwaway branch first.

Public upload directory is the classic footgun. If the configured path resolves under the document root, you have a directory where anonymous users write files and the web server executes .php. Move storage outside the docroot, or at minimum add an nginx/.htaccess rule denying script execution in that path. Also disable directory listing.

Orphaned files accumulate silently. Upload-then-attach means every abandoned form leaves a file on disk forever. Add a scheduled prune job (cron/console command) that deletes staged files with no owning record older than N hours. Do this on day one, not after the disk fills.

Filename handling is naive. Expect the original name to be used or lightly sanitized. Store original name in your DB for display, store a hashed/uuid name on disk, and sanitize aggressively — path traversal via ../ in the filename, and collision overwrites, are both plausible in code this old.

Config quirks. Settings are likely container parameters in parameters.yml/config.yml, not a semantic bundle config tree, so config/packages/*.yaml will not do anything and config validation won't help you. Typos surface as runtime "file not writable" errors. Check permissions on the target dir and run as the same user as the web server.

Debugging sequence: debug:router | grep -i upload → debug:container | grep -i upload → tail the web server log while POSTing with curl -F → add a temporary dump()/var_dump in the controller if the JSON shape is unclear. The Symfony profiler is your friend for the request/response cycle but will not show filesystem failures.

Extension points, ranked by safety: (1) decorate the uploader service, (2) event subscriber on kernel/request if no domain events exist, (3) compiler pass to swap a service ID, (4) fork. Stop at (3). Never patch vendor/ in place — the next composer install erases it.

Alternatives worth evaluating before you invest: for Symfony, oneup/uploader-bundle is maintained and covers chunked/jQuery-File-Upload style flows; Symfony's own symfony/mime + a small controller is often enough. For Laravel, Storage plus the pattern above is genuinely less work than fighting a decade-old bundle — the value here is the pattern, not the package.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin