Tiger_Media_Storage_S3

@api Β· implements Tiger_Media_Storage_Interface

Tiger_Media_Storage_S3 β€” Amazon S3 (and S3-compatible) media storage.

One bucket holds everything; visibility selects a key prefix (not a separate bucket) so a single bucket policy can expose only the public prefix:

  • PUBLIC files land under public_prefix (default public/) β†’ url() returns a direct CDN/S3 URL (make that prefix world-readable via a CloudFront distribution or a bucket policy β€” modern buckets block object ACLs, so we don't rely on public-read by default).
  • PRIVATE files land under private_prefix (default private/) β†’ url() returns a short-lived presigned GET URL (presign_ttl), so S3 serves the bytes directly while the app still gates who gets handed a URL. If presigning is disabled, url() returns '' and the media layer streams through the ACL-checked /media/file/ route instead.

Credentials come from the default AWS provider chain (an EC2/ECS IAM role, env, or shared config) unless key+secret are set in the disk config. endpoint + use_path_style point it at an S3-compatible service (MinIO, DigitalOcean Spaces, R2).

Requires aws/aws-sdk-php (optional dependency β€” see composer suggest / MEDIA.md); the adapter throws a clear message if it's missing, and only loads when the s3 disk is used.

Methods

__construct()

__construct(array $config)

Build the S3 adapter from a disk config array.

  • $config array β€” the disk config (bucket required; plus optional region,

Throws RuntimeException β€” when bucket is missing

put()

put($key, $sourcePath, $visibility, $mime = null)

Upload a file from a local path to the bucket.

  • $key string β€” the storage key
  • $sourcePath string β€” local file path to upload
  • $visibility string β€” PUBLIC or PRIVATE (selects the key prefix)
  • $mime string|null β€” optional content-type

write()

write($key, $bytes, $visibility, $mime = null)

Write in-memory bytes to the bucket.

  • $key string β€” the storage key
  • $bytes string β€” the object body
  • $visibility string β€” PUBLIC or PRIVATE (selects the key prefix)
  • $mime string|null β€” optional content-type

get()

get($key, $visibility)

Fetch an object's full contents.

  • $key string β€” the storage key
  • $visibility string β€” PUBLIC or PRIVATE (selects the key prefix)

Returns string β€” the object bytes

Throws RuntimeException β€” when the object is not found

stream()

stream($key, $visibility)

Open a readable stream for an object (live socket when possible, else a temp buffer).

  • $key string β€” the storage key
  • $visibility string β€” PUBLIC or PRIVATE (selects the key prefix)

Returns resource β€” a readable stream handle

Throws RuntimeException β€” when the object is not found

delete()

delete($key, $visibility)

Delete an object (idempotent β€” deleting a missing key still succeeds).

  • $key string β€” the storage key
  • $visibility string β€” PUBLIC or PRIVATE (selects the key prefix)

exists()

exists($key, $visibility)

Report whether an object exists.

  • $key string β€” the storage key
  • $visibility string β€” PUBLIC or PRIVATE (selects the key prefix)

Returns bool β€” true when the object exists

size()

size($key, $visibility)

Return an object's size in bytes (0 when missing).

  • $key string β€” the storage key
  • $visibility string β€” PUBLIC or PRIVATE (selects the key prefix)

Returns int β€” the byte length, or 0 if not found

url()

url($key, $visibility, $ttl = null)

Build a URL for an object: a direct public URL, or a short-lived presigned GET for private.

Returns '' for private objects when presigning is disabled, so the media layer streams through the ACL-checked route instead.

  • $key string β€” the storage key
  • $visibility string β€” PUBLIC or PRIVATE (selects the key prefix)
  • $ttl int|null β€” override the presign lifetime (seconds) for a private object

Returns string β€” the object URL, or '' when no direct/presigned URL is available