hozien/laravel-awesome-uploader
Production-ready, pluggable file uploader for Laravel with Blade/React/Vue components. Supports any file type, disk storage (local/S3), JSON API responses, optional DB records + soft deletes, policies/guest uploads, hash deduplication, thumbnails, image processing, and cleanup tools.
Installation:
composer require hozien/laravel-awesome-uploader
php artisan vendor:publish --provider="Hozien\AwesomeUploader\AwesomeUploaderServiceProvider"
php artisan migrate
config/awesome-uploader.php) and migrations (database tables for uploads).Configuration:
config/awesome-uploader.php to define:
default_disk).allowed_mimes).max_size).thumbnail).database).'allowed_mimes' => ['image/jpeg', 'image/png', 'application/pdf'],
'max_size' => 10 * 1024 * 1024, // 10MB
'thumbnail' => [
'enabled' => true,
'width' => 200,
'height' => 200,
],
First Upload (Blade):
{!! AwesomeUploader::fileInput(['name' => 'document', 'multiple' => true]) !!}
use Hozien\AwesomeUploader\Facades\AwesomeUploader;
public function store(Request $request) {
$upload = AwesomeUploader::upload($request->file('document'));
return response()->json($upload);
}
First Upload (API):
upload endpoint (if enabled in config):
POST /api/upload
Form-Data: file=@/path/to/file.jpg
{
"path": "uploads/2023/10/file.jpg",
"url": "https://example.com/storage/uploads/2023/10/file.jpg",
"type": "image/jpeg",
"name": "file.jpg",
"size": 102400,
"file_hash": "a1b2c3..."
}
{!! AwesomeUploader::fileInput([
'name' => 'profile_picture',
'accept' => 'image/*',
'max_files' => 1,
'preview' => true,
'delete' => true, // Enable soft delete
]) !!}
'blade' => [
'styles' => [
'container' => 'custom-upload-container',
'preview' => 'custom-preview-class',
],
],
import { useAwesomeUploader } from 'laravel-awesome-uploader';
function MyComponent() {
const { upload, files, isUploading } = useAwesomeUploader({
endpoint: '/api/upload',
maxFiles: 5,
allowedTypes: ['image/jpeg', 'image/png'],
});
return <input type="file" onChange={(e) => upload(e.target.files)} />;
}
<template>
<awesome-uploader
endpoint="/api/upload"
:max-files="3"
:allowed-types="['application/pdf']"
@uploaded="handleUploaded"
/>
</template>
// routes/api.php
Route::post('/upload', [UploadController::class, 'store']);
public function store(Request $request) {
$upload = AwesomeUploader::upload($request->file('file'), [
'user_id' => auth()->id(),
'custom_metadata' => ['source' => 'api'],
]);
return response()->json($upload);
}
use Hozien\AwesomeUploader\Models\Upload;
$uploads = Upload::where('user_id', auth()->id())
->where('type', 'like', 'image/%')
->orderBy('created_at', 'desc')
->paginate(10);
$user = User::with(['uploads' => function($query) {
$query->where('is_primary', true);
}])->find(1);
config/awesome-uploader.php:
'thumbnail' => [
'enabled' => true,
'width' => 300,
'height' => 300,
'format' => 'webp',
'path' => 'thumbnails/{year}/{month}',
],
$upload = AwesomeUploader::upload($file);
$thumbnail = AwesomeUploader::generateThumbnail($upload->path, 150, 150);
$existing = AwesomeUploader::findByHash($request->file('file')->hash());
if ($existing) {
return response()->json(['message' => 'File already exists', 'upload' => $existing]);
}
$upload = AwesomeUploader::upload($file, ['overwrite' => true]);
// app/Policies/UploadPolicy.php
public function before($user) {
if ($user->isAdmin()) return true;
}
public function delete($user, Upload $upload) {
return $upload->user_id === $user->id;
}
Route::middleware(['auth', 'can:upload'])->group(function () {
// Upload routes
});
$uploads = AwesomeUploader::uploadMultiple($request->file('files'), [
'user_id' => auth()->id(),
'batch_id' => 'user_avatar_update_' . time(),
]);
$batch = Upload::where('batch_id', 'user_avatar_update_12345')->get();
$upload = AwesomeUploader::upload($file, [
'disk' => 's3',
'folder' => 'custom-folder',
]);
public_path('storage') is symlinked to your storage disk:
php artisan storage:link
AwesomeUploader::upload($file, [
'queue' => 'uploads',
'dispatch' => true,
]);
php artisan queue:work --queue=uploads
AwesomeUploader::extendValidation(function ($request, $file, $rules) {
$rules->merge(['dimensions' => 'min_width:1000,max_width:5000']);
});
$rules = [
'mimes' => ['image/jpeg', 'image/png'],
'max_size' => auth()->user()->plan->max_upload_size,
];
AwesomeUploader::upload($file, ['rules' => $rules]);
upload-started, upload-progress, upload-success, upload-error events.
Example (Vue):
<awesome-uploader
@upload-progress="handleProgress"
@upload-error="handleError"
/>
AwesomeUploader::afterUpload(function ($upload) {
// Send notification, update database, etc.
event(new Uploaded($upload));
});
intervention/image is missing, thumbnails will fail silently. Install it explicitly:
composer require intervention/image
php artisan migrate
How can I help you explore Laravel packages today?