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

Presigned Uploader Bundle Laravel Package

vadage/presigned-uploader-bundle

Symfony bundle that generates presigned upload URLs so clients can send files directly to cloud storage such as S3. Keeps credentials server-side, offloads large transfers from your application, and simplifies secure direct-to-storage uploads with minimal configuration.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install the two halves separately. The PHP side is composer require vadage/presigned-uploader-bundle; the browser side is npm i @vadage/presigned-uploader-bundle. In a Laravel app you will typically use the package for its presigned-URL contract + Stimulus controller, and do the actual signing with Laravel's own Storage facade rather than adopting the bundle's Symfony DI wiring.
  • Look here first: package.json and dist/upload_controller.js in the published npm tarball. Release v0.2.1 exists specifically because those two files were missing from the export map, so version >=0.2.1 is the first one where the package is actually consumable by an asset build. Then read assets/controllers.json to see the controller's default identifier (upload) and its fetch mode.
  • First use case: a direct-to-S3 upload from a Blade form. Add data-controller="upload" to a file input, point it at a tiny Laravel endpoint that returns Storage::disk('s3')->temporaryUploadUrl($key, now()->addMinutes(10)), and let the controller PUT straight to the bucket — no file body ever transits PHP.

Implementation Patterns

  • Manual controller registration under Laravel. assets/controllers.json is a Symfony UX convention; laravel-vite-plugin does not read it. Register explicitly in resources/js/app.js:

    import { Application } from '@hotwired/stimulus'
    import UploadController from '@vadage/presigned-uploader-bundle/dist/upload_controller.js'
    
    const app = Application.start()
    app.register('upload', UploadController)
    

    Import from dist/... rather than the bare package specifier — that path is now a guaranteed export as of v0.2.1.

  • Keep the presign endpoint dumb and scoped. A single POST /uploads/presign that validates content_type and size, derives the key server-side (uploads/{user_id}/{uuid}), and returns { url, key, headers }. Never accept a client-supplied key — that is a bucket-write primitive.

  • Mirror the signature in validation. Whatever headers you sign (usually Content-Type, sometimes Content-Length) must be sent byte-identical by the controller. If the controller sends Content-Type: image/png and you signed image/PNG, S3 returns a 403 that looks like a credential problem.

  • Drive the UI off Stimulus events, not polling. Bind data-action="upload:progress->form#update" and upload:success->form#enableSubmit; disable the submit button until success so you never persist a row pointing at an object that never landed.

  • Test the build, not just the PHP. The v0.2.1 bug was invisible to Composer and to any PHP test — it only surfaced at npm run build. Add a CI step that runs the frontend build, which is the only reliable regression guard for this class of packaging failure.

  • Verify server-side before persisting. After the client reports success, Storage::disk('s3')->exists($key) (or a HEAD) in the form-request handler before writing the DB record.

Gotchas and Tips

  • This release is a fix for a hard build break — pin >=0.2.1. The symptoms are exact and worth recognising: with Webpack Encore the build failed as soon as the package was listed (The file "@vadage/presigned-uploader-bundle/package.json" could not be found); with vite-plugin-symfony it failed only once the upload controller was enabled, because assets/controllers.json eager-resolves the controller module lazily. If you are on v0.2.0 or earlier under Vite, the error appears at controller-enable time, not install time, which makes it easy to misattribute to your own config.
  • Diagnose export-map issues directly. node -e "console.log(require.resolve('@vadage/presigned-uploader-bundle/package.json'))" tells you in one line whether the file is actually in the tarball. npm pack --dry-run shows the published file list and catches missing files/exports entries before you blame your bundler.
  • Stimulus controller, not a Laravel package. There is no service provider, no config file, no publishable migration here — so do not expect php artisan vendor:publish to give you anything. Everything that matters lives in dist/ and assets/controllers.json.
  • CORS is the usual culprit for a silent failure. A presigned PUT that fails preflight looks identical in the console to a bad signature. Set AllowedMethods: PUT, POST, GET, HEAD and ExposeHeaders: ETag on the bucket, and confirm the Origin matches your local port exactly.
  • Expiry vs. mobile uploads. Ten-minute URLs are fine on wifi and fail on a train. Either raise the expiry to 30–60 minutes or re-presign on retry; the controller will not refresh the URL for you.
  • Extension points: swap the controller entirely by registering your own identifier and copying the target/action contract; decorate the presign endpoint with a Laravel middleware for rate limiting and quota; the assets/controllers.json entry tells you exactly which data attributes the controller reads, which is the fastest way to learn the contract without reading dist/ minified source.
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.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle