File Upload Module
Multi-file Upload
Upload multiple files with drag & drop support, progress tracking, and error handling.
Drop files here
Any file type (max. 50 MiB)
Single Image Upload
Upload a single image file with preview and validation.
Drop your image here
PNG, JPEG, JPG, GIF, WEBP (max. 10 MiB)
Installation
1: Install the Module
You can install the upload module using the shadcn registry system:
This command will install the necessary JavaScript dependencies, shadcn/ui components, and add the SignedUrlController.php to your application.
2: Configure Routes
Reference the SignedUrlController in your routes file
Route::post('/upload/signed-url',
\App\Http\Controllers\Astrify\SignedUrlController::class
)
// if the environment is public be sure to require auth
//->middleware(['auth'])
->name('upload.signed-url');
3: Install Laravel Dependencies
Install the Flysystem S3 package via the Composer package manager:
composer require league/flysystem-aws-s3-v3:^3.0
4: Configure your S3 Storage
For local development we recommend using MinIO for locally-hosted S3-compatible storage. There are many ways to run MinIO on your machine but the remaining steps will assume you ran it in Docker with the following command:
docker run \
-p 9000:9000 -p 9001:9001 \
-v "$HOME/minio-data:/data" \
quay.io/minio/minio server /data --console-address ":9001"
Next login to the MinIO console at http://localhost:9001 using the default credentials (minioadmin
/ minioadmin
) and create a new bucket called my-bucket
.
Finally set the following environment variables in your .env
file:
AWS_BUCKET=my-bucket
AWS_ACCESS_KEY_ID=minioadmin
AWS_USE_PATH_STYLE_ENDPOINT=true
AWS_SECRET_ACCESS_KEY=minioadmin
AWS_DEFAULT_REGION=us-east-1
AWS_URL=http://127.0.0.1:9000/my-bucket
AWS_ENDPOINT=http://127.0.0.1:9000
If you're using a real Amazon S3 bucket don't forget to configure the bucket's CORS policy to allow POST requests from your domain.
Usage
This usage example provides a full page Inertia component. It integrates the upload module into an Inertia form submission. It demonstrates how to pass references for the successfully uploaded files to the Inertia useForm hook and how to prevent form submission until all file uploads are completed. The route examples shows how to validate and receive the files in your Laravel route or controller.
Security Notes
This module is designed to ensure secure file uploads to your S3 bucket. Here’s an overview of the process:
-
Private bucket configuration: Your S3 bucket should be configured as private. This prevents users from uploading or accessing files directly and ensures all access goes through temporary signed URLs issued by your Laravel application.
-
Requesting a signed URL: The client requests a signed URL from the
SignedUrlController
, providing metadata about the file(s) to be uploaded: name, size, type, and SHA256 hash. -
Server-side validation: Before issuing a signed URL, the server validates the provided metadata. If any check fails, the request is denied.
- File size (must not exceed configured limits)
- File type (must match allowed MIME types)
- SHA256 hash (used for file integrity verification)
-
URL generation: If validation passes, the server returns a signed URL containing the verified metadata.
-
Upload enforcement: If the client attempts to upload a file that does not match the metadata encoded in the signed URL, the S3 storage will reject the upload.
-
Tamper protection: If the client modifies any claims in the signed URL, the signature becomes invalid and the S3 storage will reject the upload.
Next Steps: Try implementing the upload component in your application and customize it to match your specific requirements.