/simple-s3

Simple S3 is a simple PHP client built on top of official AWS SDK

Primary LanguagePHPMIT LicenseMIT

Simple S3 Client

license Packagist Scrutinizer Code Quality Code Coverage

Simple S3 Client is a simple wrapper of the official SDK PHP Client.

Basic Usage

To instantiate the Client do the following:

use Matecat\SimpleS3\Client;

$s3Client = new Client([
    'version' => 'latest',   // REQUIRED 
    'region' => 'us-west-2', // REQUIRED
    'credentials' => [       // OPTIONAL 
        'key' => 'YOUR-ACCESS-KEY', 
        'secret' => 'YOUR-SECRET-KEY', 
        'token' => 'SESSION-TOKEN', 
    ]
];

Please note that if you don't provide the credentials array, the Client will try to get values from the following environments variables on your system as the original S3Client:

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • AWS_SESSION_TOKEN

If you instead want to authenticate assuming an IAM Role in another AWS Account do the following:

use Matecat\SimpleS3\Client;

$s3Client = new Client([
    'version' => 'latest',
    'region' => 'us-west-2',
    'iam' => [ 
        'arn' => 'arn:aws:iam::123456789012:role/xaccounts3acces', 
        'session' => 's3-access-example', 
    ]
];

For further config details please refer to the official documentation:

Configuration for the AWS SDK for PHP Version 3

Methods

Here is the list of Client's public methods:

  • clearBucket - clear a bucket from all files
  • copyFolder - copy the items from a folder to another one
  • copyItem - copy an item from a bucket to another one
  • copyInBatch - copy in batch items from a bucket to another one
  • createBucketIfItDoesNotExist . create a bucket if it does not exists
  • createFolder . create an empty folder in a bucket if it does not exists
  • deleteBucket - delete a bucket
  • deleteBucketPolicy - delete the bucket policy
  • deleteFolder - delete a folder
  • deleteItem - delete an item
  • downloadItem - download an item
  • enableAcceleration - enable the acceleration mode for a bucket
  • getBucketLifeCycle get the bucket lifecycle configuration
  • getBucketPolicy get the bucket policy
  • getBucketSize get the size (in Bytes) of files in a bucket
  • getItem - get all informations for an item
  • getItemsInABucket get an array of items in a bucket
  • getItemsInAVersionedBucket get an array of items in a versioned bucket
  • getCurrentItemVersion - get the latest version of an item
  • getPublicItemLink - get the public link to download the item
  • hasBucket - check if a bucket exists
  • hasFolder - check if a folder exists
  • hasItem - check if an item exists
  • isBucketVersioned - check if bucket has versioned enabled
  • openItem - get the content of an item
  • restoreItem - try to restore an item from archive
  • setBucketLifecycleConfiguration - set bucket lifecycle configuration
  • setBucketPolicy - set the bucket policy
  • setBucketVersioning - set the bucket versioning
  • transfer - transfer content from/to buckets
  • uploadItem - upload an item to a bucket from a file
  • uploadItemFromBody - upload an item to a bucket from the body content

Naming validation for buckets and objects

Please refer to the official AWS policy:

The Client comes with two validators:

  • S3BucketNameValidator
  • S3ObjectSafeNameValidator

These two classes throws you an InvalidS3NameException if the name provided is not compliant with the AWS rule conventions.

Validators are invoked in Client's createBucketIfItDoesNotExist, uploadFileFromBody and uploadFile methods.

Objects name escaping

Please read carefully the object safe naming rules.

Escaping object names is entirely up to you.

You can use the provided Matecat\SimpleS3\Components\Encoders\UrlEncoder class, or inject in Client your own encoder if you prefer, but please note that it MUST implement Matecat\SimpleS3\Components\Encoders\SafeNameEncoderInterface interface:

...

use Matecat\SimpleS3\Components\Encoders\UrlEncoder;

$encoder = new UrlEncoder();
$s3Client->addEncoder($encoder);

Filename trimming

As the Amazon official documentation reports, the filename max size on S3 is 1024 characters.

But you MUST be aware of filename max size of your operating system.

For example, if you run the application on a Linux system, this limit is 255 bytes, so you cannot download a file with a name which exceeds this value.

S3Client comes with a FilenameTrimmer helper class, which automatically trims the filenames. Default limit value is 255.

To override this limit, use setFilenameMaxSize method:

...

$client->setFilenameMaxSize(512);

Bucket lifecycle

You can set the basic lifecycle for your bucket with setBucketLifecycleConfiguration method.

...

$s3Client->setBucketLifecycleConfiguration(['bucket' => $this->bucket, 'rules' => [...]]);

For further details please refer to the bucket lifecycle configuration official API documentation.

Bucket policy

You can set the bucket policy using setBucketPolicy method. Consider the following example:

...

$s3Client->setBucketPolicy([
    'bucket' => 'mauretto78-bucket-test-policy', 
    'policy' => '{
        "Version": "2012-10-17",
        "Id": "Versioning",
        "Statement": [
            {
                "Effect": "Deny",
                "Principal": "*",
                "Action": "s3:GetBucketVersioning",
                "Resource": "arn:aws:s3:::mauretto78-bucket-test-policy"
            }
        ]
    }'
]);

You can grab bucket policy and delete it by using respectively getBucketPolicy and deleteBucketPolicy methods.

For further details please refer to the bucket policy official API documentation.

Bucket versioning

You can enable bucket versioning:

...

$s3Client->setBucketVersioning(['bucket' => $this->bucket]);

And now, when you use getItemsInABucket method, a <VERSION_ID> tag will be added to keys:

...

// getItemsInABucket() will return something like this:
$notHydrated = [
    'key<VERSION_ID=123456789>',
    'key<VERSION_ID=234567890>',
    'key<VERSION_ID=345678901>',
];

$hydrated = [
    'key<VERSION_ID=123456789>' => 'content',
    'key<VERSION_ID=234567890>' => 'content',
    'key<VERSION_ID=345678901>' => 'content',
];

For further details please refer to the bucket versioning official API documentation.

Restoring an item

You can use restoreItem to send a restore an archived object. You can choose between three retrieval options:

  • Bulk (lasts 5-12 hours)
  • Expedited (default, lasts 1-5 minutes)
  • Standard (lasts 3-5 hours)

For further details please refer to the official documentation:

Restore an archived object

Caching

In order speed up data retrieval, you can inject a cache handler. Please note that the cache MUST implement Matecat\SimpleS3\Components\Cache\CacheInterface. The client comes with a Redis implementation:

...

use Matecat\SimpleS3\Components\Cache\RedisCache;

$redis = new Predis\Client();
$cacheAdapter = new RedisCache($redis);
$s3Client->addCache($cacheAdapter);

Now getItemsInABucket method will get the elements directly from cache. Please note that caching works ONLY if you provide a prefix to the method:

...

// this will get keys from cache
$s3Client->getItemsInABucket([
    'bucket' => 'your-bucket', 
    'prefix' => 'prefix/',
    'hydrate' => true // false by default. If true is set the method returns an array of Aws\ResultInterface 
]);

// this will EVER get keys from S3
$s3Client->getItemsInABucket('your-bucket');

If you need to skip the cache you can add an extra parameter called exclude-cache:

...

// this will get keys from S3
$s3Client->getItemsInABucket([
    'bucket' => 'your-bucket', 
    'prefix' => 'prefix/',
    'exclude-cache' => true 
]);

Commands

If you have an application which uses Symfony Console, you have some commands available:

  • ss3:batch:transfer Transfer files from/to a bucket.
  • ss3:bucket:clear Clears a bucket.
  • ss3:bucket:create Creates a bucket.
  • ss3:bucket:delete Deletes a bucket.
  • ss3:cache:flush Flush all data stored in cache.
  • ss3:cache:stats Get the cache statistics.
  • ss3:folder:copy Copy the items from a folder to another one.
  • ss3:item:copy Copy an object from a bucket to another one.
  • ss3:item:delete Deletes an object from a bucket.
  • ss3:item:download Download an object from a bucket.
  • ss3:item:upload Upload an object into a bucket.

You can register the commands in your app, consider this example:

#!/usr/bin/env php
<?php
set_time_limit(0);

require __DIR__.'/../vendor/autoload.php';

$config = parse_ini_file(__DIR__.'/../config/credentials.ini');
$s3Client = new \Matecat\SimpleS3\Client(
    [
        'version' => $config['VERSION'],
        'region' => $config['REGION'],
        'credentials' => [
            'key' => $config['ACCESS_KEY_ID'],
            'secret' => $config['SECRET_KEY']
        ]
    ]
);

$redis = new Predis\Client();
$cacheAdapter = new \Matecat\SimpleS3\Components\Cache\RedisCache($redis);
$s3Client->addCache($cacheAdapter);

// create symfony console app
$app = new \Symfony\Component\Console\Application('Simple S3', 'console tool');

// add commands here
$app->add(new \Matecat\SimpleS3\Console\BatchTransferCommand($s3Client));
$app->add(new \Matecat\SimpleS3\Console\BucketClearCommand($s3Client));
$app->add(new \Matecat\SimpleS3\Console\BucketCreateCommand($s3Client));
$app->add(new \Matecat\SimpleS3\Console\BucketDeleteCommand($s3Client));
$app->add(new \Matecat\SimpleS3\Console\CacheFlushCommand($s3Client));
$app->add(new \Matecat\SimpleS3\Console\CacheStatsCommand($s3Client));
$app->add(new \Matecat\SimpleS3\Console\FolderCopyCommand($s3Client));
$app->add(new \Matecat\SimpleS3\Console\ItemCopyCommand($s3Client));
$app->add(new \Matecat\SimpleS3\Console\ItemDeleteCommand($s3Client));
$app->add(new \Matecat\SimpleS3\Console\ItemDownloadCommand($s3Client));
$app->add(new \Matecat\SimpleS3\Console\ItemUploadCommand($s3Client));

$app->run();

Logging

You can inject your logger to log every Client outcome call. Please note that your logger MUST be PSR-3 compliant:

...

// $logger MUST implement Psr\Log\LoggerInterface

$s3Client->addLogger($logger); 

Support

If you found an issue or had an idea please refer to this section.

Authors

License

This project is licensed under the MIT License - see the LICENSE.md file for details