Installation
composer require atom-php/uploader
Add the service provider to config/app.php:
'providers' => [
// ...
Atom\Uploader\UploaderServiceProvider::class,
],
Basic Configuration Publish the config file:
php artisan vendor:publish --provider="Atom\Uploader\UploaderServiceProvider"
Key config options in config/uploader.php:
default_disk: Set your default storage disk (e.g., public, s3).allowed_mimes: Define allowed file types (e.g., ['image/jpeg', 'image/png']).max_size: Set max file size in KB (e.g., 10240 for 10MB).First Use Case: Uploading a File
use Atom\Uploader\Uploader;
$uploader = app(Uploader::class);
$result = $uploader->upload(
file: $request->file('avatar'),
options: [
'disk' => 'public',
'path' => 'avatars',
'filename' => 'custom_name.jpg',
]
);
path, url, and original_name.Embeddable Uploads
Create an Upload model with an Uploadable trait:
use Atom\Uploader\Traits\Uploadable;
class Profile extends Model
{
use Uploadable;
protected $uploadable = [
'avatar' => [
'disk' => 'public',
'path' => 'profile_avatars',
],
];
}
$profile = new Profile();
$profile->avatar = $request->file('avatar');
$profile->save(); // File is uploaded and path stored in DB.
Dynamic Uploads
Use the Uploader facade for ad-hoc uploads:
use Atom\Uploader\Facades\Uploader;
$path = Uploader::upload($file, [
'disk' => 's3',
'path' => 'dynamic_uploads',
]);
Batch Processing Process multiple files in a loop:
$files = $request->file('documents');
$results = [];
foreach ($files as $file) {
$results[] = $uploader->upload($file, ['path' => 'documents']);
}
Pre-Upload Validation Extend validation logic before upload:
$validator = Validator::make($request->all(), [
'file' => [
'required',
'file',
'mimes:jpeg,png,pdf',
function ($attribute, $value, $fail) {
if ($value->getSize() > 5 * 1024 * 1024) {
$fail('File too large. Max 5MB.');
}
},
],
]);
Post-Upload Actions Chain actions after upload (e.g., generate thumbnails):
$result = $uploader->upload($file, ['path' => 'images']);
$this->generateThumbnail($result['path']);
Fallback Disks Define fallback disks in config:
'fallbacks' => [
'public' => 's3',
's3' => 'local',
],
Disk Misconfiguration
filesystems.php is properly configured for the disks you reference in uploader.php.php artisan storage:link
Filename Collisions
filename is not provided, the package uses a UUID. Override this in options:
'filename' => 'user_' . auth()->id() . '.jpg'
Str::uuid() for unique filenames:
'filename' => Str::uuid() . '.' . $file->extension()
Large File Handling
post_max_size and upload_max_filesize in php.ini are adjusted.ORM Sync Issues
Uploadable trait, ensure your model’s fillable includes the upload field name (e.g., avatar).MassAssignmentException if the field isn’t fillable.Log Upload Events
Enable logging in config/uploader.php:
'log' => [
'enabled' => true,
'channel' => 'single',
],
storage/logs/laravel.log.Verify File Paths
Storage::disk('public')->exists($path) to check if a file was saved.dd($result) after upload to inspect the returned data.Common Errors
FileNotFoundException: Check if the file exists ($request->hasFile('field')).InvalidArgumentException: Validate MIME types or disk configuration.Custom Storage Strategies Bind a custom storage adapter:
$uploader->extend('custom', function () {
return Storage::disk('custom_disk');
});
'disk' => 'custom'
Event Listeners
Listen for upload events (e.g., Atom\Uploader\Events\FileUploaded):
// In EventServiceProvider
protected $listen = [
'Atom\Uploader\Events\FileUploaded' => [
'App\Listeners\LogUpload',
],
];
Middleware for Uploads Restrict uploads to authenticated users or roles:
$uploader->middleware(function ($request, $next) {
if (!$request->user()->can('upload-files')) {
abort(403);
}
return $next($request);
});
Testing Uploads
Use UploadTestCase or mock the Uploader facade:
$this->partialMock(Uploader::class, function ($mock) {
$mock->shouldReceive('upload')
->once()
->andReturn(['path' => 'test.jpg']);
});
How can I help you explore Laravel packages today?