Upload, Resize and Save images with Intervention Image v3 in Laravel Storage. Test UploadedFile::fake() with real image file.
<form action="/upload/avatar" method="post" enctype="multipart/form-data">
@csrf
<label>Image</label>
<input type="file" name="image">
<input type="submit" name="submit" value="Upload">
</form>
composer require intervention/image
Here you will set the disk where our files will be saved by the Storage::put() method and from where they will be downloaded by the Storage::get() or Storage::download() methods. !!! Do not use the Storage::disk('public') method when saving files!!!
# Private files default setting (storage/app/private)
FILESYSTEM_DISK=local
# For local server public diectory (storage/app/public)
FILESYSTEM_DISK=public
# For local or remote ftp server with ssl (works well, config in StorageFtpProvider.php)
FILESYSTEM_DISK=ftp
If you want to make public disk uploaded files accessible from the web, you should create a symbolic link from directory storage/app/public to target public/storage directory.
php artisan storage:link
This is how we save files with the Storage class to (public, ftp, sftp, s3).
<?php
use Intervention\Image\ImageManager;
use Intervention\Image\Drivers\Gd\Driver;
$user = Auth::user();
$path = 'media/avatars/' . $user->id . '.webp';
// Resize uploaded image
$image = (new ImageManager(new Driver()))->read($request->file('image'))->resize(256,256)->toWebp();
// Scale proportionally uploaded image
$image = (new ImageManager(new Driver()))->read($request->file('image'))->scale(256)->toWebp();
// Crop uploaded image from center
$image = (new ImageManager(new Driver()))->read($request->file('image'))
->crop(config('default.banner_width', 1920), config('default.banner_height', 540), 0, 0, position: 'center-center')
->toWebp();
// Save file with Storage class
Storage::put($path, (string) $image);
// Save with Intervention localy private file (only example don't use here)
// $image->save(storage_path('private/avatars/abcxyz.webp'));
Here's how you can access files using the Storage class (exampe file ShowImage.php).
You may use the url method to get the URL for a given file. If you are using the public disk, this will typically just prepend /storage to the given path and return a relative URL to the file. If you are using the s3 driver, the fully qualified remote URL will be returned.
// For javascript onerror method
Route::get('img/url', function() {
return Storage::url(request($path));
return Storage::temporaryUrl(request($path), now()->addMinutes(5));
});
Here's how to get the content of file from a public disk, ftp, sftp or s3 server.
// Display image from html
<img src="image/show?path=media/avatars/1.webp">
// Display image with path from img/show route
Route::get('img/show', function() {
$path = request($path);
try {
// From storage (check null or use Throwable)
if ($path != null && Storage::exists($path)) {
return Storage::response($path);
}
} catch(\Throwable $e) {
return response()->file(public_path('/default/error.webp'));
}
return response()->file(public_path('/default/default.webp'));
}
// Get image content from storage and then display from server
$content = Storage::get($path);
return response($content)->header('Content-Type', 'image/webp');
// Get from storage scale add watermark and display
$width = request()->integer('size');
$image = (new ImageManager(new Driver()))
->read(Storage::get($path))
->scale(width: $width)
->place('images/watermark.png', 'bottom-right');
$encoded = $image->toWebp();
return response($encoded)->header('Content-Type', 'image/webp');
// Get and display file from local disk
return response(file_get_contents(storage_path('app/private/foto/secret.webp'))->header('Content-Type', 'image/webp');
Force file download in browser.
// Download file from storage
return Storage::download('orders.webp');
return Storage::download('file.webp', $name, $headers);
// Download private file from local server
return response()->download(storage_path('app/private/foto/secret.webp'));
<?php
use Illuminate\Validation\Rule;
// Max size in KB (bail for stop on first error, sometimes for validate if exists in request)
$validated = request()->validate([
'avatar' => [
'required|image|mimes:webp,jpeg,png,jpg,gif|max:2048',
'dimensions:min_width=100,min_height=100,max_width=500,max_height=500'
],
'image' => [
'bail',
'sometimes|image',
Rule::file()->types(['webp', 'jpeg', 'jpg', 'png', 'gif'])->max(2 * 1024),
Rule::dimensions()->maxWidth(1920)->maxHeight(1080),
]
]);
Test image upload with real file
<?php
$disk = config('filesystems.default', 'public');
Storage::fake($disk);
$response = $this->postJson('/web/api/upload/avatar', [
'avatar' => UploadedFile::fake()->createWithContent('avatar.webp', file_get_contents(base_path('tests\Dev\image\fake.webp'))),
// 'avatar' => UploadedFile::fake()->image('avatar.webp', 200, 200),
]);
$response->assertStatus(200)->assertJson([
'message' => 'Avatar has been uploaded.',
'avatar' => 'avatars/' . $user->id . '.webp'
]);
- https://gist.github.com/atomjoy/04991ab6fdd74565bdd9463f06bd4dfc#file-showimage-php
- https://gist.github.com/atomjoy/04991ab6fdd74565bdd9463f06bd4dfc#file-storageftpprovider-php
- https://image.intervention.io/v3/basics/image-output#handling-of-encoded-image-data
- https://laravel.com/docs/12.x/validation#manually-creating-validators
- https://laravel.com/docs/12.x/filesystem
- https://laravel.com/docs/12.x/filesystem#ftp-driver-configuration