bttr / laravel-async-aws-s3
Laravel filesystem driver backed by the AsyncAws S3 client instead of the AWS SDK.
Requires
- php: ^8.5
- async-aws/simple-s3: ^3.0
- illuminate/filesystem: ^13.0
- illuminate/support: ^13.0
- league/flysystem-async-aws-s3: ^3.31
Requires (Dev)
- laravel/pint: ^1.18
- league/flysystem-aws-s3-v3: ^3.25
- league/flysystem-path-prefixing: ^3.25
- league/flysystem-read-only: ^3.25
- orchestra/testbench: ^11.0
- pestphp/pest: ^4.0
Suggests
- league/flysystem-path-prefixing: Required to use the disk 'prefix' option (^3.25.1).
- league/flysystem-read-only: Required to use read-only disks (^3.25.1).
README
Laravel filesystem disks backed by AsyncAws
instead of the AWS SDK, using the League's
flysystem-async-aws-s3 adapter.
Requires PHP 8.5+ and Laravel 13+.
Installation
composer require bttr-nl/laravel-async-aws-s3
That is all. The package replaces Laravel's built-in s3 driver, so existing
s3 disks in config/filesystems.php keep working unchanged — including
url(), temporaryUrl(), temporaryUploadUrl() and checksum().
Once no disk uses the SDK any more you can drop it:
composer remove aws/aws-sdk-php league/flysystem-aws-s3-v3
Configuration
Disk configuration is unchanged:
's3' => [ 'driver' => 's3', 'key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), 'token' => env('AWS_SESSION_TOKEN'), 'region' => env('AWS_DEFAULT_REGION'), 'bucket' => env('AWS_BUCKET'), 'url' => env('AWS_URL'), 'endpoint' => env('AWS_ENDPOINT'), 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), 'throw' => false, ],
Supported on top of the usual keys:
| Key | Effect |
|---|---|
profile |
Read credentials from that ~/.aws/credentials profile. |
send_chunked_body |
Send aws-chunked request bodies. Off by default; needed by some S3-compatible services. |
Leave key/secret empty to use the AsyncAws credential chain: environment
variables, ~/.aws, ECS/EKS container credentials, IMDS, and web identity — so
IAM roles work without configuration.
Keeping Laravel's s3 driver
The package also registers an async-s3 driver name, always. To stop it from
claiming s3, point it at that name instead:
ASYNC_AWS_S3_DRIVER=async-s3
Disks with 'driver' => 'async-s3' then use AsyncAws while 'driver' => 's3'
stays on the AWS SDK. Publish the config to set this in a file:
php artisan vendor:publish --tag=async-aws-s3-config
Differences from the AWS SDK driver
getClient()returns anAsyncAws\SimpleS3\SimpleS3Client, not anAws\S3\S3Client. Code touching the raw client — Laravel Vapor, custom presigners, SDK middleware — needs adjusting or should stay on the SDK driver.- Unsupported disk options throw rather than being silently dropped:
credentials,signature_version,use_accelerate_endpoint,use_dual_stack_endpoint,bucket_endpoint,endpoint_providerandhttp. Options AsyncAws satisfies anyway —stream_reads,ua_append— are accepted and ignored. - No SSO credential support. AsyncAws reads static credentials, profiles,
roles assumed via web identity, and instance/container metadata — not
aws sso loginsessions. - Uploads are multipart via
SimpleS3Client::upload()(64 MB parts, overridable per write withPartSize), so objects larger than 5 GB work. - A disk's
optionsapply to writes only (write,writeStream,createDirectory), not to reads, copies or checksums. temporaryUploadUrl()returns no headers. SigV4 query signing puts everything in the URL, so a plainPUTto it is enough.
Testing
composer install
vendor/bin/pest # unit tests; integration tests skip
The integration tests run against any S3-compatible server:
docker run -d --rm --name minio -p 9000:9000 \
-e MINIO_ROOT_USER=minioadmin -e MINIO_ROOT_PASSWORD=minioadmin \
quay.io/minio/minio:latest server /data
docker run --rm --network host --entrypoint sh quay.io/minio/mc:latest -c \
'mc alias set minio http://127.0.0.1:9000 minioadmin minioadmin; mc mb --ignore-existing minio/test-bucket'
MINIO_ENDPOINT=http://127.0.0.1:9000 vendor/bin/pest
License
MIT. See LICENSE.