async-aws/simple-s3
AsyncAws Simple S3 is a lightweight wrapper around the AsyncAws S3 client that simplifies common S3 tasks and integrations. Install via Composer and use a higher-level API for working with buckets and objects without the boilerplate of raw S3 calls.
## Getting Started
### Minimal Setup
1. **Installation**: Add the package via Composer:
```bash
composer require async-aws/simple-s3
Basic Instantiation: Initialize the client in a Laravel service or controller. Credentials are auto-loaded from environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION), but you can override them:
use AsyncAws\SimpleS3\SimpleS3Client;
$client = new SimpleS3Client();
First Use Case: Upload a file with minimal boilerplate:
$client->upload('my-bucket', 'path/to/file.pdf', fopen('/local/path/file.pdf', 'r'));
bucket: Target S3 bucket name.key: Destination path (e.g., uploads/2024/file.pdf).source: File handle (resource, SplFileInfo, or Traversable).Configuration: For non-default regions or endpoints, pass options during instantiation:
$client = new SimpleS3Client([
'region' => 'eu-west-1',
'endpoint' => 'https://s3.eu-west-1.amazonaws.com',
]);
$client->upload('bucket', 'key', fopen('local/file', 'r'));
$stream = $client->download('bucket', 'key');
file_put_contents('local/copy', $stream);
has():
if ($client->has('bucket', 'key')) { ... }
Generate time-limited URLs for client-side transfers (e.g., browser uploads):
$url = $client->getPresignedUrl(
'bucket',
'key',
'+10 minutes', // Expiration (e.g., '+5 minutes', '2024-12-31T23:59:59Z')
$versionId: 'abc123' // Optional for versioned buckets
);
Leverage AsyncAws\Core\Operation\ParallelExecutor for concurrent uploads/downloads:
use AsyncAws\Core\Operation\ParallelExecutor;
$executor = new ParallelExecutor();
$executor->run(
array_map(fn ($file) => $client->upload(...), $files)
);
Register the client as a singleton in AppServiceProvider:
public function register()
{
$this->app->singleton(SimpleS3Client::class, fn () => new SimpleS3Client());
}
public function __construct(private SimpleS3Client $s3) {}
Access the underlying S3Client for advanced operations (e.g., ACLs, CORS):
$s3Client = $client->getS3Client();
$result = $s3Client->putObject([
'Bucket' => 'bucket',
'Key' => 'key',
'ACL' => 'public-read',
]);
Filesystem to delegate to SimpleS3Client:
use Illuminate\Contracts\Filesystem\Filesystem;
class S3Filesystem implements Filesystem {
public function __construct(private SimpleS3Client $s3) {}
public function write($path, $contents, $options = []) {
$this->s3->upload('bucket', $path, fopen('php://temp', 'r+'));
}
// Implement other methods...
}
config/filesystems.php:
'disks' => [
's3' => [
'driver' => 'custom-s3',
's3' => env('AWS_BUCKET'),
],
],
use AsyncAws\SimpleS3\SimpleS3Client;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
class UploadFileJob implements ShouldQueue {
use Queueable;
public function __construct(
private SimpleS3Client $s3,
private string $bucket,
private string $key,
private string $localPath
) {}
public function handle() {
$this->s3->upload($this->bucket, $this->key, fopen($this->localPath, 'r'));
}
}
AsyncAws\Core\Exception\RuntimeException for S3-specific errors:
try {
$client->upload('bucket', 'key', $stream);
} catch (RuntimeException $e) {
report($e); // Log via Laravel's error handler
throw new \RuntimeException('Failed to upload file', 0, $e);
}
PHP Version Mismatch
RuntimeException.async-aws/simple-s3:2.x for PHP 8.1 or use a runtime check:
if (version_compare(PHP_VERSION, '8.2.0') < 0) {
throw new \RuntimeException('PHP 8.2+ required for this package version.');
}
Versioned Buckets and versionId
versionId in getPresignedUrl() or download() defaults to the latest version, which may not match expectations in versioned buckets.versionId when working with versioned objects:
$url = $client->getPresignedUrl('bucket', 'key', '+1 hour', $versionId: 'abc123');
No Automatic Retries
$retries = 3;
while ($retries--) {
try {
$client->upload(...);
break;
} catch (RuntimeException $e) {
if ($retries === 0) throw $e;
sleep(2 ** $retries); // Exponential backoff
}
}
Missing ACL/Metadata Methods
S3Client:
$s3Client = $client->getS3Client();
$s3Client->putObject([
'Bucket' => 'bucket',
'Key' => 'key',
'Metadata' => ['author' => 'John Doe'],
]);
Stream Handling Quirks
php://stdin) may fail if the package assumes seekability.$temp = tmpfile();
stream_copy_to_stream($nonSeekableStream, $temp);
rewind($temp);
$client->upload('bucket', 'key', $temp);
Multipart Upload Threshold
PartSize (default: 8MB). Adjust via:
$client = new SimpleS3Client(['multipart_upload_threshold' => 16 * 1024 * 1024]); // 16MB
Parallel Uploads
ParallelExecutor to maximize throughput:
$executor = new ParallelExecutor();
$executor->run(
array_map(fn ($file) => $
How can I help you explore Laravel packages today?