amjadiqbal / filament-url-image-uploader
A powerful Filament PHP form component that enables seamless image uploads from URLs. Features include image validation, preview functionality, and easy integration with Laravel storage. Perfect for remote image imports, content management, and e-commerce applications built with FilamentPHP.
Package info
github.com/AmjadIqbal/filament-url-image-uploader
pkg:composer/amjadiqbal/filament-url-image-uploader
Fund package maintenance!
Requires
- php: ^8.3
- filament/filament: ^4.0|^5.0
- spatie/laravel-package-tools: ^1.15.0
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.0
- nunomaduro/collision: ^8.0
- orchestra/testbench: ^9.0|^10.0|^11.0
- phpunit/phpunit: ^11.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Filament URL Image Uploader
A Filament form field with two tabs: upload an image file, or paste an image URL and fetch it server-side. Either way your model gets a plain storage path string.
Supported versions
| Package | Filament | Laravel | PHP |
|---|---|---|---|
| 2.x | 4.x and 5.x | whatever your Filament version supports (11.28+, 12.x, 13.x) | 8.3+ |
1.x (1.x branch) |
3.x | whatever Filament 3 supports | 8.3+ |
Installation
composer require amjadiqbal/filament-url-image-uploader
Composer picks the right major for your Filament version. Fetched and uploaded files are stored on
the public disk by default, so make sure it is linked:
php artisan storage:link
No panel plugin registration or asset build is needed: the field works in any Filament form.
Usage
use AmjadIqbal\FilamentUrlImageUploader\Components\UrlImageUploader; UrlImageUploader::make('image')->directory('images');
The field renders two tabs: upload a file directly, or paste an image URL and click Fetch Image
to download it server-side. Either way, the value saved to your model attribute is always a plain
storage path string (e.g. "images/example.jpg"), never an array, so no accessor or mutator is
needed on your model:
// database column: image (string, nullable) class Post extends Model { protected $fillable = ['image']; }
To render the stored image elsewhere in your app, resolve it through the disk you configured:
Storage::disk('public')->url($post->image);
What the URL fetch checks
- Only
http://andhttps://URLs are fetched (file://,php://,data:and similar are refused). - The download is capped (10 MB by default) and has a 10 second timeout.
- The downloaded bytes must be an image (checked by content, not by file extension).
- Fetched files get a random filename prefix, so two URLs with the same basename never overwrite each other.
Each failure shows a Filament notification and stores nothing. A malformed URL left in the URL tab also blocks saving with a field error.
File paths and Filament's tampering check
The field saves the storage path it was given, so it opts its inner upload out of
FileUpload::preventFilePathTampering() (opt-in from Filament 4.11 / 5.6, and on by default in the
Filament 6 development branch). That check compares a submitted path with the record's original
value for an attribute named like the upload; this field's inner upload is not a model attribute, so
with the check on every stored image would be rejected. As on Filament 4 and 5 today, a submitted
path is therefore not tied back to the record: if the disk holds files belonging to other users or
tenants, give each their own directory(). Filament 6 is not released and is not a supported
version of this package yet; this only keeps 2.x from failing on it.
Configuration
Directory
UrlImageUploader::make('image')->directory('custom/path/here');
Disk
By default, files are stored on the public disk. You can target any configured disk:
UrlImageUploader::make('image')->disk('s3');
Preserve original filenames
UrlImageUploader::make('image')->preserveFilenames();
With this on, a fetched file keeps its original name, and gets a -1, -2, ... suffix instead of
overwriting a file that already exists.
URL fetch size limit
UrlImageUploader::make('image')->maxUrlFetchSize(5 * 1024 * 1024); // 5 MB
Scope
UrlImageUploader manages a single image per field. It does not support Filament's multiple()
mode. For a gallery of several images, use a Repeater of them.
Using it in a Repeater (image gallery)
use Filament\Forms\Components\Repeater; Repeater::make('gallery') ->schema([ UrlImageUploader::make('image')->directory('gallery'), ]) ->reorderable() ->addable() ->deletable();
Each row gets its own instance of the field, so adding, deleting and reordering rows keeps every
image with its own row. This is covered by a dedicated test suite
(tests/Feature/RepeaterGalleryTest.php).
Gotcha: while a row is being edited, its live state is the field's internal {path, url}
shape, not the flat string your model attribute ends up with. If you add an itemLabel() that reads
the row's image value, read $state['image']['path'] ?? null (an array), or don't key the label off
this field at all.
Upgrading from 1.x (Filament 3)
Upgrade Filament itself first (see Filament's upgrade guide), then:
composer require amjadiqbal/filament-url-image-uploader:^2.0
The field's PHP API (make(), directory(), disk(), preserveFilenames(), maxUrlFetchSize())
and the stored value are unchanged, so your forms and data need no changes. Published translations
still apply.
Translations
All user-facing strings ship in English by default. Publish them to customize or translate:
php artisan vendor:publish --tag="filament-url-image-uploader-translations"
Testing
composer test # PHPUnit, via Orchestra Testbench composer analyse # Larastan/PHPStan (level 5) composer format # Laravel Pint scripts/ci-local.sh # all of the above on PHP 8.3 and 8.4, against Filament 5 and Filament 4
Changelog
Please see CHANGELOG.md for what changed in each release.
Security Vulnerabilities
Please report security issues privately through GitHub's private vulnerability reporting. See SECURITY.md.
Contributing
Contributions are welcome. See CONTRIBUTING.md (CI for this repo runs locally).
Custom Development
Hire me on Upwork for:
- Package integration
- Custom feature development
- Technical consultation
- Project implementation
Community Support
For priority support and enterprise solutions, please reach out via Upwork for direct assistance.
License
MIT. See LICENSE.