Installation Add the bundle via Composer:
composer require blackboxcode/pando-file-bundle
Register the bundle in config/app.php under providers:
BlackBoxCode\PandoFileBundle\PandoFileBundle::class,
Configuration Publish the default config:
php artisan vendor:publish --provider="BlackBoxCode\PandoFileBundle\PandoFileBundle" --tag="config"
Update config/pando-file.php with your storage paths, allowed MIME types, and file size limits.
First Use Case: File Upload
Inject the PandoFileManager service into a controller:
use BlackBoxCode\PandoFileBundle\Services\PandoFileManager;
public function upload(Request $request, PandoFileManager $fileManager)
{
$file = $request->file('file');
$path = $fileManager->store($file, 'uploads');
return response()->json(['path' => $path]);
}
File Storage
$path = $fileManager->store($file, 'custom/directory');
$paths = $fileManager->storeMultiple($request->file('files'), 'uploads');
config/pando-file.php to use S3, FTP, or local storage:
'disks' => [
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'bucket' => env('AWS_BUCKET'),
],
],
Then pass the disk name:
$path = $fileManager->store($file, 'uploads', 's3');
File Retrieval
$url = $fileManager->url($path);
$temporaryUrl = $fileManager->temporaryUrl($path, now()->addMinutes(10));
return $fileManager->stream($path, 'myfile.pdf');
File Management
$fileManager->delete($path);
$fileManager->deleteMultiple(['path1', 'path2']);
if ($fileManager->exists($path)) { ... }
Validation Integration
Use the PandoFileValidator to enforce rules:
use BlackBoxCode\PandoFileBundle\Validators\PandoFileValidator;
$validator = new PandoFileValidator();
$validator->validate($file, [
'mimes' => ['jpg', 'png'],
'max_size' => '2048', // KB
]);
Laravel Events
Bind to file upload events in EventServiceProvider:
protected $listen = [
'BlackBoxCode\PandoFileBundle\Events\FileUploaded' => [
'App\Listeners\LogUploadedFile',
],
];
Form Requests
Extend FormRequest to validate files:
public function rules()
{
return [
'file' => [
'required',
function ($attribute, $value, $fail) {
$validator = new PandoFileValidator();
if (!$validator->validate($value, [
'mimes' => ['pdf', 'docx'],
'max_size' => '5120',
])) {
$fail('Invalid file type or size.');
}
},
],
];
}
API Resources Transform file paths in API responses:
public function toArray($request)
{
return [
'path' => $this->fileManager->url($this->path),
'size' => $this->size,
'mime' => $this->mime,
];
}
Middleware Restrict file access by role:
public function handle($request, Closure $next)
{
if ($request->is('files/*') && !$request->user()->can('access-files')) {
abort(403);
}
return $next($request);
}
Configuration Overrides
config/pando-file.php is published and updated. Default values may not match your needs.php artisan config:clear
Disk Misconfiguration
use Illuminate\Support\Facades\Storage;
Storage::disk('s3')->put('test', 'test');
File Path Collisions
public and uploads) can cause issues.$path = $fileManager->store($file, 'app/uploads');
Validation Bypass
store($file, 'uploads', false)) can lead to security risks like directory traversal.Event Listener Conflicts
FileUploaded events, listeners may fire unexpectedly.event(new \BlackBoxCode\PandoFileBundle\Events\FileUploaded($path));
Log File Operations
Enable debug mode in config/pando-file.php:
'debug' => env('APP_DEBUG', false),
Logs will appear in storage/logs/laravel.log.
Check Storage Permissions Ensure the storage directory has write permissions:
chmod -R 775 storage/app/public
Validate File Paths
Use dd() to inspect paths before operations:
$path = $fileManager->getPath($file);
dd($path); // Verify the path is correct
Test with Small Files First Start with small files (e.g., 1KB) to rule out size-related issues before testing large uploads.
Custom Validators
Extend PandoFileValidator to add rules:
namespace App\Validators;
use BlackBoxCode\PandoFileBundle\Validators\PandoFileValidator;
class CustomFileValidator extends PandoFileValidator
{
public function validateExtension($extension)
{
return in_array($extension, ['jpg', 'jpeg', 'png']);
}
}
Use it in your code:
$validator = new CustomFileValidator();
File Processing Hooks
Override the PandoFileManager to add preprocessing:
namespace App\Services;
use BlackBoxCode\PandoFileBundle\Services\PandoFileManager;
class CustomFileManager extends PandoFileManager
{
public function store($file, $directory = 'uploads', $validate = true)
{
// Preprocess file (e.g., resize images)
if ($file->isValid() && $file->getClientOriginalExtension() === 'jpg') {
$file = $this->resizeImage($file);
}
return parent::store($file, $directory, $validate);
}
protected function resizeImage($file)
{
// Implement resize logic
}
}
Bind it in AppServiceProvider:
$this->app->bind(PandoFileManager::class, function ($app) {
return new CustomFileManager(
$app->make('storage'),
$app->make('validator')
);
});
Custom Storage Drivers
Implement BlackBoxCode\PandoFileBundle\Contracts\FileStorage to add support for new storage backends (e.g., Dropbox, Backblaze).
Event Customization
Extend the FileUploaded event to include additional data:
namespace App\Events;
use BlackBoxCode\PandoFileBundle\Events\FileUploaded as BaseFileUploaded;
class FileUploaded extends BaseFileUploaded
{
public $userId;
public function __construct($path, $userId)
{
parent::__construct($
How can I help you explore Laravel packages today?