spatie/laravel-medialibrary
Attach and manage files on Eloquent models with an easy API. Handle uploads, store media on any Laravel filesystem (local, S3, etc.), organize collections, and generate image/PDF conversions and manipulations with built-in support for responsive images.
Installation:
composer require spatie/laravel-medialibrary
Publish the config (optional but recommended for customization):
php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider"
Model Setup:
Use the HasMedia trait and RegistersMediaConversions trait (if using conversions):
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use Spatie\MediaLibrary\RegistersMediaConversions;
class Post extends Model
{
use HasMedia, InteractsWithMedia, RegistersMediaConversions;
// ...
}
First Upload:
$post = Post::find(1);
$post->addMedia($request->file('image'))->toMediaCollection('images');
addMedia().getFirstMedia() or collections with getMedia().deleteMedia() or clear collections with clearMediaCollection().Media Collections:
config/medialibrary.php or dynamically:
$post->addMedia($file)->toMediaCollection('featured_images');
$post->getMedia('images'); // Returns a Media collection
Conversions:
registerMediaConversions():
public function registerMediaConversions(Media $media = null): void
{
$this->addMediaConversion('thumb')
->width(100)
->height(100);
}
$post->getFirstMedia('images')->getUrl('thumb');
Custom Paths:
PathGenerator:
$post->addMedia($file)
->usingFileName('custom_' . $file->getClientOriginalName())
->toMediaCollection('custom_collection');
Temporary URLs:
$post->getFirstMedia('images')->getTemporaryUrl(60); // 60 seconds expiry
MediaWasAdded, MediaWasDeleted, etc., for post-processing:
event(new MediaWasAdded($post, $media));
toResponse() for API-friendly media URLs:
return $post->getFirstMedia('images')->toResponse();
$post->getMedia('images')->each(function ($media) {
$media->regenerateConversions();
});
Filesystem Configuration:
filesystems.php is properly configured for the disk you’re using (e.g., s3, local).encodePercentSigns: false in config for S3.Media Collection Naming:
Conversions:
$media->regenerateConversions();
deferred() for lazy conversion generation (v11.22.0+):
$this->addMediaConversion('thumb')->deferred();
Orphaned Files:
php artisan media:clean to remove files not referenced by any model.--hash-lookup (v11.17.8+) for faster cleanup.Custom Path Generators:
PathGenerator implements Spatie\MediaLibrary\PathGenerators\PathGenerator.getPathFor() in your model’s PathGenerator:
public function getPathFor(Media $media): string
{
return 'custom/' . $media->model->id . '/' . $media->file_name;
}
Temporary URLs:
getAvailableTemporaryUrl() (v11.20.0+) for pre-signed URLs.config/medialibrary.php:
'temporary_url_expiration' => 3600, // 1 hour
Image Drivers:
apk add --no-cache graphicsmagick
MediaWasAdded/MediaWasDeleted events to log actions:
MediaWasAdded::dispatch($model, $media);
config/medialibrary.php are correct and writable:
'disk' => 'public',
'models' => [
'post' => [
'path' => 'posts/{id}',
'conversions' => 'conversions',
],
],
spatie/pdf-to-image).Custom Media Models:
Spatie\MediaLibrary\Models\Media to add custom fields:
class CustomMedia extends Media
{
protected $casts = [
'custom_field' => 'string',
];
}
config/medialibrary.php to use your model:
'models' => [
'post' => [
'model' => CustomMedia::class,
],
],
Custom Conversions:
MediaConversion class:
class CustomConversion extends MediaConversion
{
public function manipulate($convert)
{
// Custom logic (e.g., FFmpeg for videos)
}
}
registerMediaConversions():
$this->addMediaConversion('custom')
->usingCustomManipulation(CustomConversion::class);
Custom Storage:
s3, ftp) by specifying the disk in toMediaCollection():
$post->addMedia($file)->toMediaCollection('downloads', 's3');
How can I help you explore Laravel packages today?