Laravel 10 application for CSV upload and processing with queued background jobs, Redis-backed real-time progress updates, and a local Docker workflow.
- PHP 8.3
- Laravel 10
- MySQL 8
- Redis 7
- Laravel Horizon
- Laravel WebSockets
- Vite / npm
- Upload CSV files from the web UI
- Process imports asynchronously through Laravel queues
- Broadcast import progress over WebSockets
- Update existing records from follow-up CSV uploads
- Mark failed imports when the input file is invalid
flowchart LR
U["User Browser"] -- HTTP --> A["Laravel App"]
U <-- WS progress updates --> W["WebSocket Server"]
A -- Presigned upload --> S3[("S3")]
S3 -- Upload Noti --> SQS[("SQS")]
SQS --> SL["SQS Listener"]
SL -- Trigger --> B["Background Jobs"]
B -- Get the file --> S3
B --> M["MySQL"] & W
flowchart TD
A[User opens upload page] --> B[Laravel renders page]
B --> C[User selects CSV file]
C --> D[App requests presigned S3 upload URL]
D --> E[Laravel generates presigned URL]
E --> F[Browser uploads CSV directly to S3]
F --> G[S3 sends object-created notification to SQS]
G --> H[S3 notification poller reads SQS message]
H --> I[Poller matches uploaded file record]
I --> J[Poller dispatches CSV processing jobs]
J --> K[Queue worker processes CSV in background]
K --> L[Data inserted or updated in MySQL]
K --> M[Progress broadcast over WebSocket]
M --> N[Browser shows live progress updates]
L --> O[Processing completes]
O --> P[User sees final success or failure status]
For local non-Docker development:
- PHP 8.3
- Composer 2
- Node.js 20 and npm
- MySQL 8
- Redis
For containerized development, Docker Desktop with Compose is enough.
cp .env.docker .env
docker compose up -d --build
docker compose exec laravel composer install
docker compose exec laravel npm install
docker compose exec laravel php artisan key:generate
docker compose exec laravel php artisan migrateOpen the app at http://localhost:8000.
Useful ports:
8000Laravel app6001WebSocket server3307MySQL6380Redis
More Docker detail lives in DOCKER.md and DOCKER-EXPLAINED.md.
composer install
npm install
cp .env.example .env
php artisan key:generate
php artisan migrateRun the app and supporting processes in separate terminals:
php artisan serve
php artisan queue:work
php artisan websockets:serve
npm run devIf you use Horizon locally, run:
php artisan horizonCore values used by this project:
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
REDIS_HOST=redis
REDIS_PORT=6379
QUEUE_CONNECTION=redis
BROADCAST_DRIVER=pusher
PUSHER_HOST=127.0.0.1
PUSHER_PORT=6001
PUSHER_SCHEME=httpInside Docker containers, use Compose service names such as mysql and redis. From the browser, connect to the WebSocket host exposed on your machine.
This project supports direct CSV uploads to AWS S3 and background processing triggered from S3 upload notifications delivered through Amazon SQS.
Set these environment variables when using AWS storage:
FILESYSTEM_DISK=s3
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=ap-southeast-1
AWS_BUCKET=
AWS_UPLOAD_PREFIX=csv-uploads
AWS_PRESIGN_TTL_MINUTES=10
AWS_S3_UPLOAD_NOTIFICATION_QUEUE_URL=
AWS_USE_PATH_STYLE_ENDPOINT=false
AWS_ENDPOINT=
AWS_URL=What each setting is used for:
FILESYSTEM_DISK=s3stores uploaded files on the S3 disk instead of local storage.AWS_BUCKETis the bucket used for uploaded CSV files.AWS_UPLOAD_PREFIXis the folder prefix used when generating upload paths.AWS_PRESIGN_TTL_MINUTEScontrols how long presigned upload URLs stay valid.AWS_S3_UPLOAD_NOTIFICATION_QUEUE_URLpoints to the SQS queue consumed byphp artisan s3:poll-upload-notifications.AWS_ENDPOINTandAWS_USE_PATH_STYLE_ENDPOINT=trueare useful for S3-compatible local services such as LocalStack or MinIO.
Expected AWS wiring:
- The app generates a presigned upload target for S3.
- The client uploads the CSV to S3.
- The S3 bucket sends object-created notifications to an SQS queue.
- The app polls that queue and starts CSV processing for matching uploaded files.
The queue poller can be run manually outside Docker:
php artisan s3:poll-upload-notificationsInside Docker it is already started by Supervisor in the laravel container.
If you want Laravel's queue driver itself to use Amazon SQS instead of Redis, Laravel's standard queue settings are also available in config/queue.php:
QUEUE_CONNECTION=sqs
SQS_PREFIX=https://sqs.<region>.amazonaws.com/<account-id>
SQS_QUEUE=default
SQS_SUFFIX=
AWS_DEFAULT_REGION=ap-southeast-1
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=That is separate from AWS_S3_UPLOAD_NOTIFICATION_QUEUE_URL. In the current Docker-oriented setup, the app queue driver defaults to Redis while S3 upload notifications are polled from SQS.
# Tests
php artisan test
php artisan test --testsuite=Feature
php artisan test --testsuite=Unit
# Code style
./vendor/bin/pint
./vendor/bin/pint --test
# Cache and config
php artisan optimize:clear
php artisan config:clear
php artisan cache:clear
# Queue worker reload after job changes
php artisan queue:restartDocker equivalents:
docker compose exec laravel php artisan test
docker compose exec laravel ./vendor/bin/pint
docker compose exec laravel php artisan optimize:clearTest files referenced by the original project documentation:
yoprint_test_import.csvyoprint_test_updated.csvyoprint_test_import_1m.csvyoprint_test_import - Failed.csv
Typical flow:
- Upload
yoprint_test_import.csvto create records. - Upload
yoprint_test_updated.csvto update existing records by unique keys. - Upload
yoprint_test_import - Failed.csvto verify failure handling. - Upload
yoprint_test_import_1m.csvonly in a controlled environment if you want to test large imports.
Queue workers and the WebSocket server must be running or you will not see background progress updates.
The app image is defined in docker/8.3/Dockerfile. It currently installs a focused local development toolset:
- PHP 8.3 CLI
- Composer
- Node.js and npm
- MySQL client
- Supervisor
- PHP extensions used by this app, including MySQL, Redis, XML, ZIP, BCMath, Intl, MBString, Curl, Readline, PCNTL, and POSIX
Unused extras such as PostgreSQL tooling, SQLite tooling, GD, Imagick, Xdebug, Yarn, pnpm, and Bun are intentionally excluded.
app/
database/
resources/
routes/
tests/
docker/
This project is open-sourced software licensed under the MIT license.