vx/js-upload-bundle
vx/js-upload-bundle is a Laravel/PHP package that bundles JavaScript upload assets, simplifying setup for file-upload interfaces and backend wiring. It helps organize frontend upload scripts so you can add or customize upload flows with less manual configuration.
This is a Symfony bundle, not a Laravel package — so the first step for a Laravel developer is deciding whether it's worth pulling a Symfony bundle into a Laravel repo at all. If you just need the client-side uploader script, you can install it and copy the JS; if you need the server-side routing/controller, expect to bridge Symfony's DI container and routing yourself (or run it in a separate Symfony service).
Minimal steps:
composer require vx/js-upload-bundle — check the composer.json constraints against your PHP version before committing; with 7 stars and no dependents, there's no ecosystem pressure keeping it compatible with modern Symfony/Laravel releases.Resources/config/ directory first — that's where the service definitions, default parameters (upload directory, allowed extensions, max size), and route prefixes live. This is the source of truth; READMEs on low-traffic repos drift.config/bundles.php (or AppKernel::registerBundles()); in a Laravel context, skip this and instead lift the controller/service classes into app/ or a small package of your own.Resources/config/routing.xml / .yaml) — the bundle almost certainly exposes a POST endpoint for the upload itself, which is the piece you actually need to expose.bin/console assets:install or copy Resources/public/), then wire the JS uploader to the endpoint in a single Blade/Twig view.First use case: drop the uploader widget on one form, POST a single file, and confirm the file lands in the configured directory and the response returns a JSON payload (typically a filename or ID) you can persist alongside your model. Do that end-to-end before touching multi-file, chunking, or deletion.
Treat the bundle as two halves and integrate them separately. The server half is a Symfony controller + upload handler; the client half is a JS widget. In Laravel you'll almost always want to keep the JS and reimplement the ~50-line controller using Laravel's UploadedFile and Storage facade. That's cheaper than making Symfony's HttpFoundation and container play nicely with Laravel's request lifecycle.
Single-endpoint pattern. Configure one route (e.g. POST /upload) that accepts multipart form data, validates MIME/size server-side, writes via the configured filesystem/storage service, and returns JSON { "success": true, "file": "<stored-name>" }. Your form then submits the stored name as a hidden field, and you attach it to the entity in your own controller — don't let the uploader write directly to your domain model.
Handler override pattern. Most bundles of this shape define an "upload handler" service you can swap via a service definition or config key. That's the correct extension point for custom naming, S3/Spaces storage, virus scanning, or image resizing — subclass the default handler and alias the service rather than editing vendor code.
Event/listener pattern. If the bundle dispatches a pre- or post-upload event, hook validation and persistence there. This keeps your custom logic out of the vendor directory and survives composer update.
JS wiring pattern. Initialize the uploader in a dedicated JS module (not inline), point it at a route generated server-side, and handle the complete/success callback to populate a hidden input. For multiple uploads, keep an array of returned identifiers and serialize it as JSON into one form field.
Deletion and cleanup. Pair the upload endpoint with an explicit delete route, and add a scheduled sweep for orphaned files (uploaded but never attached to a record). The bundle won't do this for you, and orphan accumulation is the most common production complaint with upload bundles.
Integration tip for Laravel specifically: put the route behind auth and throttle middleware — upload endpoints are the classic unauthenticated disk-fill vector.
X-CSRF-TOKEN. Either exclude the upload route from CSRF (and rely on auth + throttling) or explicitly forward the token in the uploader's headers config.allowedExtensions config that's also enforced client-side. Verify server-side MIME sniffing and size limits yourself; never trust the filename extension.cache:clear; stale parameters are the usual cause of "my upload dir change did nothing."Resources/public/ require re-running assets:install --symlink or webpack-encore rebuild. Silent stale-asset bugs are common.composer.json, read the handler code before shipping, and be prepared to fork. Don't build a core product feature on it without a mental exit plan.enctype, wrong field name, or a proxy body-size limit (client_max_body_size in nginx).How can I help you explore Laravel packages today?