Installation Add the package via Composer:
composer require atom-php/uploader-bundle
Publish the default configuration:
php artisan vendor:publish --provider="Atom\UploaderBundle\UploaderBundle" --tag=config
Basic Configuration
Edit config/uploader.php to define storage adapters (e.g., local, s3, ftp). Example:
'adapters' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app/uploads'),
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'bucket' => 'my-bucket',
],
],
First Upload
Inject the UploaderInterface into a controller/service and use it:
use Atom\UploaderBundle\Uploader\UploaderInterface;
public function uploadFile(Request $request, UploaderInterface $uploader)
{
$file = $request->file('file');
$path = $uploader->upload($file, 'local'); // 'local' is the adapter name
return response()->json(['path' => $path]);
}
File Validation Use Laravel’s built-in validation to ensure files meet requirements before uploading:
$request->validate([
'file' => 'required|file|max:10240', // 10MB max
]);
Multi-Adapter Uploads Dynamically switch adapters based on business logic (e.g., upload to S3 for production, local for staging):
$adapter = config('app.env') === 'production' ? 's3' : 'local';
$path = $uploader->upload($file, $adapter);
Custom Storage Paths Override the default path per adapter in the config or dynamically:
$path = $uploader->upload($file, 'local', [
'path' => 'custom/folder/' . $user->id,
]);
File Processing
Chain file operations (e.g., resize, rename) using the UploaderInterface:
$path = $uploader->upload($file, 'local', [
'rename' => true, // Auto-generate filename
'processors' => [
'resize' => ['width' => 800, 'height' => 600],
],
]);
Batch Uploads Process multiple files in a loop:
foreach ($request->file('files') as $file) {
$path = $uploader->upload($file, 'local');
// Store path in DB or queue for further processing
}
Integration with Laravel Filesystem
Use the returned path with Laravel’s Storage facade:
$url = Storage::disk('local')->url($path);
Events
Listen to Atom\UploaderBundle\Events\FileUploaded for post-upload actions (e.g., notifications, DB updates):
event(new FileUploaded($path, $adapter, $file));
Middleware Restrict uploads to authenticated users or roles via middleware:
Route::middleware(['auth', 'upload.access'])->post('/upload', ...);
Testing
Mock the UploaderInterface in tests:
$this->partialMock(UploaderInterface::class, function ($mock) {
$mock->shouldReceive('upload')->andReturn('fake/path.jpg');
});
Adapter Configuration
config/uploader.php or misconfiguring credentials (e.g., missing AWS_SECRET_ACCESS_KEY).php artisan config:clear after changes. Use .env for sensitive data.File Overwrites
rename: true will overwrite existing files.rename: true or implement a custom naming strategy:
'rename' => function ($file) {
return 'custom-' . Str::uuid() . '.' . $file->extension();
}
Permissions
chmod -R 775 storage/app/uploads
Large Files
php.ini:
upload_max_filesize = 20M
post_max_size = 20M
max_execution_time = 300
Processor Conflicts
resize) fail silently or corrupt files.try {
$uploader->upload($file, 'local', ['processors' => [...]]);
} catch (\Exception $e) {
Log::error('Upload failed: ' . $e->getMessage());
}
Enable Verbose Logging
Add to config/uploader.php:
'debug' => env('APP_DEBUG', false),
Check logs in storage/logs/laravel.log.
Check Returned Paths Always log or dump the returned path to verify the file was saved:
dd($uploader->upload($file, 'local')); // Debug path
Validate Adapters Test each adapter manually:
$uploader->testAdapter('s3'); // Returns boolean
Custom Adapters Extend the bundle by creating a new adapter:
namespace App\Uploader;
use Atom\UploaderBundle\Uploader\AdapterInterface;
class CustomAdapter implements AdapterInterface {
public function upload($file, array $options) { ... }
public function delete($path) { ... }
}
Register it in config/uploader.php:
'adapters' => [
'custom' => [
'driver' => 'custom',
'class' => App\Uploader\CustomAdapter::class,
],
],
Custom Processors
Add new processors (e.g., watermark) by extending the Processor class:
namespace App\Uploader\Processors;
use Atom\UploaderBundle\Uploader\Processor;
class WatermarkProcessor extends Processor {
public function process($filePath) { ... }
}
Use it in the upload options:
'processors' => [
'watermark' => ['text' => 'Confidential'],
],
Event Customization Override default event behavior by binding to the event in a service provider:
public function boot()
{
event(new FileUploaded($path, $adapter, $file));
}
Queue Uploads Offload uploads to a queue for async processing:
dispatch(new HandleUpload($file, $adapter, $options));
Create a job:
namespace App\Jobs;
use Atom\UploaderBundle\Uploader\UploaderInterface;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
class HandleUpload implements ShouldQueue {
use Queueable;
public function handle(UploaderInterface $uploader) {
$uploader->upload($this->file, $this->adapter, $this->options);
}
}
How can I help you explore Laravel packages today?