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 Fileapi Laravel Package

unisharp/laravel-fileapi

UniSharp Laravel FileAPI provides a simple Laravel integration for handling file uploads and file management. It offers a convenient API for validating, storing, and retrieving uploaded files, helping add file features to Laravel apps with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

This release is a maintenance + interoperability drop for an image upload/thumbnail package. Nothing here changes the public API shape, so an existing install can be upgraded with a composer update and, at most, a config re-publish.

Minimal steps:

  1. composer require <vendor>/<package> (or bump to ^1.0.2).
  2. Publish the config so you own the knobs you are about to rely on:
    php artisan vendor:publish --tag=config
    
  3. Point the package at a disk in config/filesystems.php. Local is fine for the first run; the new GCS support means gcs is now a first-class target alongside s3.
  4. Build the smallest possible flow — one upload, one thumbnail — and confirm where the files land:
    $path = imageUpload($request->file('avatar'))
        ->disk('public')
        ->thumbnails([200, 400])
        ->save('avatars');
    

Where to look first: the published config file (disks, quality, suffix, thumbnail sizes) and the package's README/CHANGELOG. The changelog is the fastest way to see which of the fixes below touch your current setup.

First real use case: a profile/avatar upload that produces a small set of derived sizes on public with storage:link in place. Once that works end to end, promoting to S3 or GCS is a config change, not a code change.

Implementation Patterns

Thumbnails are now optional — make that explicit. 1.0.2 allows uploading without thumbnails. Prefer passing an empty set over relying on a global default, so intent is visible at the call site:

imageUpload($file)->thumbnails([])->save('documents');

This is the right pattern for "store the original, render sizes on demand" flows, and it halves write latency on cloud disks.

Suffix is your filename contract. With empty suffixes now permitted, you can produce deterministic names (user-42.jpg instead of user-42_thumb.jpg). Beware collisions: several sizes on the same disk will overwrite each other if the suffix is empty. If you go suffix-less, give each size its own directory:

->suffix('')          // new in 1.0.2
->thumbnails([200])   // writes into thumbnails/ subfolder

Quality is a per-type decision. jpg at quality 100 was previously clamped/broken; it now works. Treat 100 as an exception for hero images and print exports, not a default — it can multiply file size several-fold for no perceptible gain. Keep 80–85 globally and override narrowly:

->quality(100)->save('heroes');   // only where it matters

Cloud disks: configure visibility once, in two places. The thumbnail-visibility fix means derived files now inherit the visibility you asked for, but the disk and the package must agree. On S3/GCS:

// config/filesystems.php
'gcs' => [
    'driver' => 'gcs',
    'project_id' => env('GOOGLE_CLOUD_PROJECT_ID'),
    'bucket'   => env('GOOGLE_CLOUD_STORAGE_BUCKET'),
    'key_file_path' => env('GOOGLE_CLOUD_KEY_FILE'),
    'visibility' => 'public',
],

Then pass the same visibility through the upload call so originals and thumbnails match. If you are on uniform bucket-level access in GCS, per-object ACLs are ignored entirely — use a public bucket or serve through signed URLs instead.

Wrap uploads in a service, not controllers. A thin ImageService that owns disk, quality, sizes, and suffix keeps the inevitable policy drift in one file. It also makes the "with thumbnails / without thumbnails" branch a one-liner rather than a controller if.

Queue anything with more than two sizes. Cloud round-trips for each derived image are slow; dispatch a job that uploads the original synchronously and generates variants after the response.

Gotchas and Tips

  • Animated GIFs: retest, don't assume. 1.0.2 fixes frame loss during compression, but verify with a real multi-frame GIF at your configured quality. GIF is palette-based; quality settings intended for JPEG can still degrade it. Consider skipping compression for GIFs entirely and storing the original.
  • jpg + quality 100 is a trap in disguise. The bug is fixed, but you will now actually get the huge file. Add a size guard before persisting.
  • Visibility on third-party clouds has two failure modes. (a) The disk has no visibility set, so files default to private and your CDN 403s; (b) the bucket enforces uniform access, so the ACL request is silently dropped. Check the stored object's ACL, not just the returned path.
  • Empty suffix + multiple sizes = overwrites. Always pair suffix('') with per-size directories, or keep a suffix on all but the primary.
  • Config caching bites after upgrade. If you deploy with config:cache, re-publish and re-cache. A stale cached config is the most common cause of "GCS isn't working" right after a version bump.
  • GCS credentials are path-based. key_file_path must be an absolute path readable by the PHP user; JSON blobs in env vars won't work. Ship the key as a secret mounted file, never in the repo.
  • Existing rows may reference thumbnails that were never written. If previous versions silently failed on thumbnail generation, your database has paths to nothing. Run a one-off backfill job over affected records rather than a lazy fix on error.
  • Extension points to prefer: the config file (sizes, quality, suffix, disk) and the storage driver abstraction. Avoid patching the package's compressor directly — the GIF and JPEG fixes in this release both touch that path, so local patches will conflict on the next bump.
  • Debugging order for a missing/odd image: 1) Storage::disk($d)->exists($path), 2) the disk's visibility config, 3) php artisan config:show filesystems, 4) package log channel. Ninety percent of issues land at step 1 or 3.
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.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel