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

Laravel Uppy S3 Multipart Upload Laravel Package

tapp/laravel-uppy-s3-multipart-upload

Laravel package that provides backend endpoints for Uppy's AWS S3 multipart uploader, handling create, sign, complete, and abort requests so large files upload directly to S3 via presigned URLs with minimal server overhead.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

What the package actually is. tapp/laravel-uppy-s3-multipart-upload is a thin server-side adapter that implements the endpoints Uppy's @uppy/aws-s3 plugin expects for S3 multipart uploads: create a multipart upload, sign individual parts, list parts, complete, and abort. It wraps aws/aws-sdk-php (or the Flysystem S3 adapter) and exposes them as a publishable Laravel route group plus a config file. It is glue code, not a platform — realistically a few hundred lines of controller and config.

Architecture fit.

  • Strong fit for a Laravel monolith, Inertia/Blade app, or Laravel API serving a SPA on the same or a trusted origin. The value proposition is direct-to-S3 upload: bytes never traverse the app server, PHP only mints presigned URLs.
  • Weak fit for teams already running Uppy Companion (Node), teams on non-S3 storage, or teams that need server-side virus scanning/transcoding in the upload path (this bypasses the app entirely).
  • Architectural dependency: it makes the browser dependent on the Laravel app being reachable and authenticated for the signing calls only. That is a meaningful availability coupling — if the API is down, uploads cannot start or resume, even though S3 is healthy.

Integration feasibility. Low effort mechanically: composer require, publish config, register routes, point Uppy at the endpoint prefix, configure IAM and bucket CORS. The real effort is not installation, it is hardening: the package is intentionally unopinionated about auth, key naming, size limits, and content-type allow-listing. Everything a reviewer would ask about — who may upload, to which prefix, how large, of what type — is your code, not the package's.

Technical risk.

  • Adoption/bus factor: 83 stars, 0 dependents, single-maintainer origin (TappNetwork). No ecosystem signal. This is the dominant risk, but it is mitigated by the fact that the code is small and MIT — a fork or in-house reimplementation is a day of work, not a quarter.
  • Security surface: presigned URL generation driven by client-supplied key, uploadId, and part numbers. If the controller trusts those inputs, a user can upload over another tenant's key, enumerate parts, or complete an upload they did not start. Verify key prefixing/scoping, uploadId ownership binding, TTLs, and size/type enforcement before shipping.
  • Version drift: dependency on Laravel major versions and aws/aws-sdk-php/Flysystem S3 signatures. The 2025-11-25 release is recent, which is reassuring, but a package this small can go quiet without anyone noticing until a Laravel upgrade.
  • Cost abuse: open signing endpoints are a denial-of-wallet vector. Rate limiting and per-user quotas are mandatory.

Key questions to resolve in the technical spike.

  1. Does the controller derive the object key server-side, or accept it from the client? If client-supplied, how is it constrained?
  2. How does it bind an uploadId to the authenticated user, and what stops a replay of another user's uploadId?
  3. Are part-size defaults sensible against S3's 10,000-part cap and 5GB per-part cap for the file sizes we actually expect?
  4. Does it clean up aborted/orphaned multipart uploads, or do we own a lifecycle rule?
  5. Is it using the Laravel filesystems disk config (reusable, testable) or its own raw credential handling?
  6. Test coverage and CI matrix — are Laravel 10/11/12 and PHP 8.1–8.3 actually exercised?
  7. What is the escape hatch? Can we swap the package for our own controller without touching the frontend (i.e., is the contract just Uppy's HTTP API)?

Integration Approach

Stack fit. Assumes Laravel 9+ with PHP 8.1+, an S3 (or S3-compatible) bucket, and a JS frontend that can add @uppy/aws-s3. S3-compatible targets (MinIO, Cloudflare R2) generally work but differ on multipart semantics and ETag CORS exposure — validate with a spike before committing. If you are on a signed-URL/Laravel-Flysystem pattern already, this slots in cleanly; if you are on a proxied-upload pattern, this is a genuine architecture change, not an increment.

Alternatives to weigh before adopting.

  • Uppy Companion: mature, but another Node service to run, secure, and patch.
  • Hand-rolled controller: ~200–300 lines, full control, zero third-party risk, but you own the edge cases (part signing, abort, completion validation).
  • This package: fastest path to a working direct-to-S3 multipart flow, at the cost of a small external dependency. Given the low stars, the honest framing is "adopt as a reference implementation you are willing to fork," not "adopt as a supported library."

Migration path.

  1. Run a timeboxed spike (2–3 days) in a non-production environment: large-file upload through the package with a real bucket, IAM scoped to the required S3 actions, CORS configured, and an auth-wrapped route group.
  2. If the spike passes, introduce it behind a feature flag on a single, non-critical upload surface (e.g., attachments on one resource type) rather than the primary document flow.
  3. Keep the frontend contract at Uppy's HTTP API so the backend is swappable without a UI release.
  4. Only after a release cycle of clean operation, expand to other upload surfaces.

Compatibility checklist.

  • Laravel/PHP version against the package's CI matrix and your framework version.
  • aws/aws-sdk-php constraint conflicts with anything already pulling it in (Flysystem, SES, SQS).
  • Route prefix collisions with existing routes/api.php and any Inertia catch-all route.
  • Auth middleware: Sanctum/session CSRF for SPA calls; the signing endpoints must not be api-public by default.
  • Bucket CORS: AllowedHeaders must include the headers Uppy sends (x-amz-*, content-type), and ExposeHeaders must include ETag.
  • IAM policy scoped to s3:PutObject, s3:AbortMultipartUpload, s3:ListMultipartUploadParts, s3:CompleteMultipartUpload on a specific prefix — not s3:*.

Sequencing. Infrastructure (bucket policy, CORS, IAM) → package install + config + auth wrapping → server-side validation layer (key scoping, size/type caps, uploadId ownership) → frontend Uppy integration → lifecycle rule for aborted uploads → observability → rollout behind flag.

Operational Impact

Maintenance. Low ongoing code maintenance, moderate dependency-watch overhead. Pin the version, enable Dependabot/Renovate, and assign explicit ownership. Because the package is small, keep a fork (or a vendored controller) in your back pocket: the exit cost is measured in hours. Budget a recurring "does this still work with the next Laravel major" check — that is the realistic failure point, not feature stagnation.

Support. No vendor, no SLA, community GitHub issues only. Internal support means one or two engineers who understand the multipart flow. Document the auth wrapping and validation layer as yours, so on-call does not chase a third-party repo at 2am.

Scaling. Excellent on the data plane — bytes go browser→S3, and S3 scales far beyond anything the app tier will see. The app tier only signs URLs and completes uploads, so cost is a small number of short requests per file, roughly one per part. Watch two things: (1) signing endpoint request rate under concurrency — presigning is cheap but it is still a PHP request per part, so a 100GB upload at 10MB parts is ~10,000 signing calls; tune part size upward (25–50MB) to keep requests tractable; (2) per-user concurrency and bandwidth quotas, since nothing throttles the client's direct-to-S3 throughput.

Failure modes to design for.

  • Orphaned multipart uploads: the most common and most expensive failure. Browser closed mid-upload leaves parts billed for storage with no visible object. Mandatory S3 lifecycle rule (AbortIncompleteMultipartUpload after 1–7 days) and an alert.
  • Presigned URL expiry during long uploads: slow connections re-request signed parts; ensure the client retries the signing endpoint, and set TTLs long enough (15–60 min) for typical part durations.
  • CORS/ETag misconfiguration: presents as opaque browser "network error" with no server log. Budget debugging time and document the required bucket CORS.
  • Credential rotation: IAM key rotation breaks signing silently; prefer instance/task roles over static keys.
  • Completion validation gap: the client reports success; the server must verify the object exists at the expected key and size before recording it in the database. Never trust the client's completion call alone.
  • Abuse: unauthenticated or unthrottled signing endpoints allow arbitrary writes and cost inflation.

Ramp-up. A mid-level Laravel engineer can integrate the package in about a day; hardening (key scoping, uploadId ownership, size/type enforcement, lifecycle rules) is realistically 3–5 days; frontend Uppy configuration and large-file testing another 2–3 days. Include an integration test with a 100MB+ file and a deliberately interrupted upload — that exercise surfaces CORS, ETag, abort, and presign-expiry issues that unit tests will not.

Bottom line for a TPM. Technically adequate and strategically low-commitment: it is a small, MIT-licensed adapter over AWS's own SDK, so the real risk is not lock-in but the security and lifecycle work the package deliberately leaves to you. Approve it as a starting point with the auth/validation layer treated as first-class scope, a feature-flagged rollout, and a documented willingness to fork. Do not adopt it as a "supported dependency" that nobody owns.

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.
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen