elamed123 / laravel-temp-media
Laravel package for handling temporary media uploads with automatic cleanup
Installs: 84
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/elamed123/laravel-temp-media
Requires
- php: ^8.1|^8.2|^8.3
- spatie/laravel-medialibrary: ^10.0|^11.0
This package is auto-updated.
Last update: 2025-12-26 17:02:52 UTC
README
A comprehensive Laravel package for handling temporary media uploads with automatic cleanup and secure transfer to permanent models using Spatie Media Library.
โจ Features
- ๐ Temporary File Management - Upload and manage temporary media files with automatic expiration
- ๐ Secure Transfer System - Transfer temporary media to permanent models with validation
- ๐งน Automatic Cleanup - Built-in cleanup system for expired and processed files
- ๐ Session Security - Session-based ownership validation for enhanced security
- ๐ก Event System - Comprehensive event system for custom integrations
- ๐ฏ Type Safety - Full PHP 8.1+ type declarations and strict typing
- ๐ PSR Compliance - Adheres to PSR standards for clean, maintainable code
- ๐งช Comprehensive Testing - Full test suite with factories and examples
- โก Performance Optimized - Efficient database queries and background processing
๐ Requirements
- PHP 8.1, 8.2, or 8.3
- Laravel 8.0 or higher
- Spatie Media Library 10.0 or 11.0
๐ Quick Start
Installation
composer require elamed123/laravel-temp-media
Publish Configuration and Migrations
php artisan vendor:publish --provider="Medox\LaravelTempMedia\TempMediaServiceProvider" --tag="temp-media-config" php artisan vendor:publish --provider="Medox\LaravelTempMedia\TempMediaServiceProvider" --tag="temp-media-migrations"
Run Migrations
php artisan migrate
Configure Environment Variables
Add to your .env file:
TEMP_MEDIA_TTL_HOURS=24 TEMP_MEDIA_MAX_SIZE=10485760 TEMP_MEDIA_DISK=public TEMP_MEDIA_AUTO_CLEANUP=true
๐ฏ Basic Usage
Upload Temporary Media
Using the API
const formData = new FormData(); formData.append('file', fileInput.files[0]); fetch('/api/v1/temp-media', { method: 'POST', body: formData, headers: { 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content } }) .then(response => response.json()) .then(data => { console.log('Upload successful:', data); });
Using the Service
use Medox\LaravelTempMedia\Contracts\TempMediaServiceInterface; class MediaController extends Controller { public function upload(Request $request, TempMediaServiceInterface $tempMediaService) { $file = $request->file('file'); $sessionId = $request->input('session_id', session()->getId()); $result = $tempMediaService->uploadTempMedia($file, $sessionId); return response()->json($result->toJsonResponse()); } }
Transfer to Permanent Model
Using the Trait
use Medox\LaravelTempMedia\Traits\HandlesTempMedia; use Medox\LaravelTempMedia\DTOs\TempMediaTransferDTO; use Medox\LaravelTempMedia\DTOs\TempMediaItemDTO; use Spatie\MediaLibrary\HasMedia; class Post extends Model implements HasMedia { use HandlesTempMedia; public function attachTempMedia(array $tempMediaIds, string $collectionName = 'images') { $items = array_map( fn($id) => new TempMediaItemDTO($id), $tempMediaIds ); $transferDto = new TempMediaTransferDTO($items); return $this->transferTempMedia($transferDto, $collectionName); } }
Using the Service
use Medox\LaravelTempMedia\Contracts\MediaTransferServiceInterface; use Medox\LaravelTempMedia\DTOs\TempMediaTransferDTO; use Medox\LaravelTempMedia\DTOs\TempMediaItemDTO; class PostController extends Controller { public function store(Request $request, MediaTransferServiceInterface $transferService) { $post = Post::create($request->validated()); $tempMediaIds = $request->input('temp_media_ids', []); $items = array_map( fn($id) => new TempMediaItemDTO($id), $tempMediaIds ); $transferDto = new TempMediaTransferDTO($items); $result = $transferService->transferTempMediaToModel($post, $transferDto, 'images'); return response()->json([ 'post' => $post, 'media_transfer' => $result->toArray() ]); } }
๐ API Reference
Endpoints
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/v1/temp-media |
Upload temporary media |
GET |
/api/v1/temp-media/{id} |
Get temporary media details |
DELETE |
/api/v1/temp-media/{id} |
Delete temporary media |
POST |
/api/v1/temp-media/validate |
Validate temporary media IDs |
Response Examples
Upload Response
{
"success": true,
"data": {
"id": 1,
"url": "https://example.com/storage/temp_files/...",
"original_name": "image.jpg",
"mime_type": "image/jpeg",
"size": 1024000,
"expires_at": "2024-01-02T12:00:00.000000Z",
"is_temporary": true
},
"message": "File uploaded successfully"
}
Transfer Response
{
"transferred_media": [
{
"id": 123,
"temp_media_id": "1",
"url": "https://example.com/storage/images/...",
"collection": "images",
"original_name": "image.jpg",
"size": 1024000,
"mime_type": "image/jpeg",
"order": 1
}
],
"transferred_count": 1,
"failed_transfers": [],
"failed_count": 0,
"target_model_type": "App\\Models\\Post",
"target_model_id": "1",
"collection_name": "images"
}
โ๏ธ Configuration
The package provides extensive configuration options:
// config/temp-media.php return [ // Basic settings 'default_ttl_hours' => 24, 'max_file_size' => 10 * 1024 * 1024, // 10MB 'allowed_mime_types' => [ 'image/jpeg', 'image/png', 'image/webp', 'image/gif', ], // Security 'validate_session' => true, 'rate_limiting' => [ 'enabled' => true, 'max_attempts' => 60, 'decay_minutes' => 1, ], // Cleanup 'enable_auto_cleanup' => true, 'cleanup_schedule' => [ 'frequency' => 'hourly', 'without_overlapping' => true, 'run_in_background' => true, ], // Events 'dispatch_events' => true, // Media conversions 'generate_conversions' => false, ];
๐งน Cleanup
Automatic Cleanup
The package automatically cleans up expired and processed media hourly. You can configure this in the config file.
Manual Cleanup
# Clean up all expired and processed media php artisan temp-media:cleanup # Clean up only expired media php artisan temp-media:cleanup --expired-only # Clean up only processed media php artisan temp-media:cleanup --processed-only # Dry run to see what would be cleaned php artisan temp-media:cleanup --dry-run
Programmatic Cleanup
use Medox\LaravelTempMedia\Contracts\TempMediaServiceInterface; use Medox\LaravelTempMedia\Contracts\MediaTransferServiceInterface; // Clean up expired media $expiredCount = app(TempMediaServiceInterface::class)->cleanupExpired(); // Clean up processed media $processedCount = app(MediaTransferServiceInterface::class)->cleanupProcessedTempMedia();
๐ก Events
The package dispatches several events for custom integrations:
TempMediaUploaded
use Medox\LaravelTempMedia\Events\TempMediaUploaded; Event::listen(TempMediaUploaded::class, function (TempMediaUploaded $event) { // Handle upload event Log::info('Media uploaded', ['id' => $event->tempMedia->id]); });
MediaTransferred
use Medox\LaravelTempMedia\Events\MediaTransferred; Event::listen(MediaTransferred::class, function (MediaTransferred $event) { // Handle transfer event Notification::send($event->targetModel->user, new MediaTransferredNotification()); });
TempMediaExpired
use Medox\LaravelTempMedia\Events\TempMediaExpired; Event::listen(TempMediaExpired::class, function (TempMediaExpired $event) { // Handle expiration event Log::info('Media expired', ['id' => $event->tempMedia->id]); });
๐งช Testing
Running Tests
# Run all tests php artisan test # Run specific test suite php artisan test --testsuite=Feature php artisan test --testsuite=Unit
Test Example
use Medox\LaravelTempMedia\Tests\TestCase; use Illuminate\Http\UploadedFile; use Illuminate\Support\Facades\Storage; class TempMediaUploadTest extends TestCase { public function test_can_upload_temporary_media() { Storage::fake('public'); $file = UploadedFile::fake()->image('test.jpg'); $response = $this->postJson('/api/v1/temp-media', [ 'file' => $file ]); $response->assertStatus(201) ->assertJsonStructure([ 'success', 'data' => [ 'id', 'url', 'original_name', 'mime_type', 'size', 'expires_at', 'is_temporary' ] ]); } }
๐ง Advanced Features
Custom Media Properties
$customProperties = [ 'alt_text' => 'Product image', 'category' => 'product', 'featured' => true ]; $result = $transferService->transferTempMediaToModel( $model, $transferDto, 'images', $customProperties );
Order Management
$items = [ new TempMediaItemDTO('temp-id-1', 1), // First position new TempMediaItemDTO('temp-id-2', 2), // Second position new TempMediaItemDTO('temp-id-3', 3), // Third position ]; $transferDto = new TempMediaTransferDTO($items);
Media Conversions
Enable thumbnail generation:
// In config/temp-media.php 'generate_conversions' => true,
This generates:
thumb: 300x300 pixels with sharpeningsmall: 150x150 pixels
๐ Troubleshooting
Common Issues
File Upload Fails
- Check file size limits in configuration
- Verify MIME type is allowed
- Ensure file is valid (not corrupted)
- Check rate limiting settings
Transfer Fails
- Ensure temporary media IDs are valid and not expired
- Check that target model implements HasMedia interface
- Verify session ownership if session validation is enabled
Cleanup Not Working
- Check if auto cleanup is enabled
- Verify scheduler is running
- Run manual cleanup command
๐ค Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
๐ License
This package is open-sourced software licensed under the MIT license.
๐จโ๐ป Author
Elabidi Mohammed
- Email: mohammed.elabidi123@gmail.com
- GitHub: @elamed123
๐ Acknowledgments
- Spatie for the excellent Media Library package
- Laravel for the amazing framework
- All contributors who help improve this package
๐ Documentation
For complete documentation, please visit the Documentation file.
๐ Changelog
Please see CHANGELOG for more information on what has changed recently.
Made with โค๏ธ for the Laravel community