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

Filament Upload Laravel Package

asmit/filament-upload

asmit/filament-upload is a Filament plugin for Laravel that streamlines file uploads in admin panels with a dedicated upload field, drag-and-drop support, progress feedback, and dependable handling of large files. Ideal for adding polished media and file upload workflows to Filament resources and fo...

View on GitHub
Deep Wiki
Context7

Getting Started

1. Confirm compatibility before anything else. This package is a Filament form-field plugin (PDF upload + inline preview), so its version constraint against filament/filament is the single most important line in its composer.json. As of v2.1.0 the package claims a three-major compatibility matrix — Filament v3, v4, and v5.7+ — so check the actual constraint rather than trusting the release note:

  • composer.json → require block (filament/filament, php, livewire/livewire)
  • CHANGELOG.md / releases → which Filament majors the latest tag targets
  • src/ → does the field implement HasEmbeddedView / call toEmbeddedHtml()? (v2.1.0 added this path; it tells you which renderer your Filament version will use)
  • README.md → the published field class name and any config publish command

With 45 stars and zero dependents there is no community safety net, so read the source before trusting it in a client project.

2. Install into a scratch Filament panel first — and install ^2.1 deliberately.

composer require asmit/filament-upload:^2.1
php artisan vendor:publish --tag="filament-upload-config"   # if the tag exists
php artisan vendor:publish --tag="filament-upload-views"    # usually required for the preview blade

Anything below v2.1.0 will throw "View [components.file-upload] not found" on Filament v5.7+, so the version floor is not optional on modern Filament. If no publish tags are registered, check the package's service provider (src/*ServiceProvider.php) for what it actually publishes — a missing view publish is the usual cause of a blank preview.

3. Your first use case: replace a plain FileUpload on an existing Resource form.

use Asmit\FilamentUpload\Forms\Components\PdfUpload; // verify exact FQCN in src/

PdfUpload::make('document')
    ->label('Contract PDF')
    ->disk('private')
    ->directory('contracts')
    ->maxSize(10240)
    ->required();

The value proposition is that you get the dropzone, the stored-file lifecycle, and a rendered first-page preview in one component — instead of wiring FileUpload + a custom view() + a PDF thumbnailer yourself.

4. Where to look first when it misbehaves. In order: the field class (does it extend FileUpload or BaseField? does it branch between a Blade view and an embedded renderer?), the Blade view it renders, then the config file. Because it likely wraps Filament's own FileUpload, many "package bugs" are actually your disk visibility or livewire.temporary_file_upload settings.

Implementation Patterns

Resource form + table column pairing. The preview lives in the form; for the table you still want a clickable link. Keep the package scoped to the form and add a plain action/column yourself:

// Table
Tables\Columns\TextColumn::make('document')
    ->formatStateUsing(fn ($state) => $state ? basename($state) : '—')
    ->url(fn ($record) => $record->document ? Storage::disk('private')->url($record->document) : null)
    ->openUrlInNewTab();

Preview inside a modal action. The strongest day-to-day use is an infolist/modal "View PDF" action rather than a form field, since you rarely need to edit a PDF — you need to inspect it. Wrap the component (or its Blade view) in a ->modalContent() on a table action so reviewers can eyeball the document without downloading it.

Pair with a status field, not with validation logic. PDFs are usually evidence attached to a record. Let the package handle upload + preview, and keep "is this the approved version" in your own boolean/status column. Don't try to encode approval workflows into the upload field.

Use a dedicated disk per document type. ->disk('contracts')->visibility('private') keeps sensitive PDFs off the public disk. Then serve previews through a signed, authenticated route rather than a public URL:

Route::get('/documents/{record}/pdf', fn (Record $record) => response()->file(
    Storage::disk('contracts')->path($record->document)
))->middleware(['auth', 'can:view,record']);

Versioning pattern. Since uploads overwrite by default, snapshot the old path into a document_history JSON column in your afterStateUpdated/save hook before Filament replaces the file. This is cheap insurance and the package won't do it for you.

Integration with tests. Filament uploads are Livewire uploads, so test with the standard fakes:

Livewire::test(EditRecord::class, ['record' => $record->id])
    ->fillForm(['document' => UploadedFile::fake()->create('a.pdf', 500, 'application/pdf')])
    ->call('save')
    ->assertHasNoFormErrors();
Storage::disk('contracts')->assertExists($record->fresh()->document);

Because the package adds a custom view and (since v2.1.0) an embedded-renderer fallback, assert the page renders (assertSee) — a view-name typo or a broken fallback surfaces only at render time, and only on the Filament major you actually run. Run this test against your pinned Filament version, not just whatever CI resolves.

Fallback integration point — now two seams, not one. If the preview's markup doesn't fit your design, don't fork. Subclass the field and override view() to point at your own Blade file, keeping the upload behaviour intact. Since v2.1.0 the component may render via toEmbeddedHtml() instead of a Blade view, so if you override view() you must also override toEmbeddedHtml() (or otherwise force the Blade path) — otherwise your custom markup silently disappears on Filament v5.7+ while working fine on v4.

class AppPdfUpload extends \Asmit\FilamentUpload\Forms\Components\PdfUpload
{
    protected string $view = 'forms.components.my-pdf-upload';

    public function toEmbeddedHtml(): string
    {
        return view($this->view, ['field' => $this])->render();
    }
}

Upgrade-test the renderer, not just the class. The v2.0.0 → v2.1.0 change was purely a rendering-path fix. That means the risky surface of this package is the view layer, so a smoke test that mounts the field on each Filament major you support is worth more than unit-testing the upload logic (which is Filament's).

Gotchas and Tips

View [components.file-upload] not found means you're on the wrong package version. Filament v5.7 removed filament-forms::components.file-upload in favour of the HasEmbeddedView / toEmbeddedHtml() renderer. Fix = upgrade to v2.1.0+. If you cannot upgrade, pin Filament below v5.7 — do not "fix" it by publishing a stub view with that name, you'll be maintaining a copy of upstream markup.

License is NOASSERTION. This is the biggest red flag for commercial work — it means GitHub could not detect a recognised license, so there may be no license file, or a non-standard one. Open LICENSE and read it, or get written clarification before shipping this to a client. Absence of a license legally means all rights reserved. A new release does not change this.

Zero dependents — treat every version as unreviewed. Pin exactly ("asmit/filament-upload": "2.1.0") and commit composer.lock, especially now: a caret range spanning three Filament majors means a future release can change behaviour for you without any Filament upgrade on your side. Vendor the field class into your own project if the package is small — for a 45-star single-purpose plugin this is often the lowest-risk path.

Preview not rendering is almost always storage, not the package. Checklist, in order:

  1. APP_URL correct — Storage::url() produces broken hosts behind proxies/Docker.
  2. Symlink exists: php artisan storage:link for public-disk files.
  3. Blade view published, and view cache cleared (php artisan view:clear) — published views are cached aggressively.
  4. Livewire temp upload succeeds; if the file never persists, the preview has nothing to show.
  5. You are on v2.1.0+ if Filament is v5.7+ (see above — this presents as a hard exception, not a blank preview).

PDF embedding browser behaviour. If the preview is an <iframe>/<object>, it silently fails when:

  • The response sends X-Frame-Options: DENY or a restrictive Content-Security-Policy frame-src (common on Laravel apps behind security middleware).
  • The file is served with Content-Type: text/plain or application/octet-stream, or as an attachment — force Content-Disposition: inline and application/pdf.
  • The URL is a cross-origin S3/CDN link — many browsers refuse to embed cross-origin PDFs. Serve through your own streamed route instead.

Size limits live in three places. ->maxSize() is Filament-side only. Also set upload_max_filesize, post_max_size, and Livewire's livewire.temporary_file_upload.rules / max_upload_time. A 20 MB PDF failing with no error message is a PHP config problem, not a validation one.

Editing an existing record. The state for an already-uploaded file is a string path, not a file — if the component assumes an array/TemporaryUploadedFile, you'll get exceptions or an empty preview on edit forms while create forms work fine. Test both paths explicitly, and test them on the renderer your Filament version uses.

Debugging strategy. Dump the component state in the Blade view with @dump($getState()); if the embedded renderer is in play, dd() inside toEmbeddedHtml() or override it temporarily to log state. Because this is a thin wrapper, one dd() tells you whether the failure is "no path in state" (yours) or "path present, preview broken" (theirs).

Filament major upgrades will break it — v2.1.0 is the proof. A single-maintainer preview component is highly exposed to Filament asset/Blade/namespace changes, and this release exists purely because upstream deleted a view. Wrap it in your own App\Forms\Components\PdfUpload that extends the package class — then an upgrade means editing one file instead of every resource.

Accessibility and fallback. Always render a download link next to the preview; embedded PDF viewers are inaccessible, unsupported on most mobile browsers, and blocked in some corporate environments. The embedded preview is a convenience, the link is the feature.

Contribution calculus — slightly improved. The v2.1.0 fix came from an outside contributor (@zvizvi, PR #11), which is a good sign: the project is not a dead single-author repo, and the responsive-PR path works. It's still a one-maintainer, 45-star package with no dependents — budget for fixing bugs yourself, and note that compatibility bumps against new Filament versions remain the highest-value contribution you can make (and the one you'll end up writing).

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
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