matecat /
simple-s3
| 1 | <?php |
||
| 2 | /** |
||
| 3 | * This file is part of the Simple S3 package. |
||
| 4 | * |
||
| 5 | * (c) Mauro Cassani<https://github.com/mauretto78> |
||
| 6 | * |
||
| 7 | * For the full copyright and license information, please view the LICENSE |
||
| 8 | * file that was distributed with this source code. |
||
| 9 | * |
||
| 10 | */ |
||
| 11 | |||
| 12 | namespace Matecat\SimpleS3\Commands\Handlers; |
||
| 13 | |||
| 14 | use Aws\CommandInterface; |
||
| 15 | use Aws\Exception\MultipartUploadException; |
||
| 16 | use Aws\ResultInterface; |
||
| 17 | use Aws\S3\MultipartUploader; |
||
| 18 | use Exception; |
||
| 19 | use InvalidArgumentException; |
||
| 20 | use Matecat\SimpleS3\Commands\CommandHandler; |
||
| 21 | use Matecat\SimpleS3\Components\Validators\S3ObjectSafeNameValidator; |
||
| 22 | use Matecat\SimpleS3\Components\Validators\S3StorageClassNameValidator; |
||
| 23 | use Matecat\SimpleS3\Exceptions\InvalidS3NameException; |
||
| 24 | use Matecat\SimpleS3\Helpers\File; |
||
| 25 | |||
| 26 | class UploadItem extends CommandHandler |
||
| 27 | { |
||
| 28 | const int MAX_FILESIZE = 6291456; // 6 Mb |
||
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
| 29 | |||
| 30 | /** |
||
| 31 | * Upload a file to S3. |
||
| 32 | * Il filesize is > 6Mb a multipart upload is performed. |
||
| 33 | * For a complete reference of put object see: |
||
| 34 | * https://docs.aws.amazon.com/cli/latest/reference/s3api/put-object.html?highlight=put |
||
| 35 | * |
||
| 36 | * @param array $params |
||
| 37 | * |
||
| 38 | * @return bool |
||
| 39 | * @throws Exception |
||
| 40 | */ |
||
| 41 | 10 | public function handle(array $params = []): bool |
|
| 42 | { |
||
| 43 | 10 | $bucketName = $params[ 'bucket' ]; |
|
| 44 | 10 | $keyName = $params[ 'key' ]; |
|
| 45 | 10 | $source = $params[ 'source' ]; |
|
| 46 | |||
| 47 | 10 | if (isset($params[ 'bucket_check' ]) and true === $params[ 'bucket_check' ]) { |
|
| 48 | $this->client->createBucketIfItDoesNotExist(['bucket' => $bucketName]); |
||
| 49 | } |
||
| 50 | |||
| 51 | 10 | if (false === S3ObjectSafeNameValidator::isValid($keyName)) { |
|
| 52 | 1 | throw new InvalidS3NameException(sprintf('%s is not a valid S3 object name. [' . implode(', ', S3ObjectSafeNameValidator::validate($keyName)) . ']', $keyName)); |
|
| 53 | } |
||
| 54 | |||
| 55 | 9 | if ((isset($params[ 'storage' ]) and false === S3StorageClassNameValidator::isValid($params[ 'storage' ]))) { |
|
| 56 | throw new InvalidArgumentException(S3StorageClassNameValidator::validate($params[ 'storage' ])[ 0 ]); |
||
| 57 | } |
||
| 58 | |||
| 59 | 9 | if (File::getSize($source) > self::MAX_FILESIZE) { |
|
| 60 | return $this->multipartUpload($bucketName, $keyName, $source, $params); |
||
| 61 | } |
||
| 62 | |||
| 63 | 9 | return (new UploadItemFromBody($this->client))->handle([ |
|
| 64 | 9 | 'bucket' => $bucketName, |
|
| 65 | 9 | 'key' => $keyName, |
|
| 66 | 9 | 'body' => File::open($source), |
|
| 67 | 9 | 'storage' => (isset($params[ 'storage' ])) ? $params[ 'storage' ] : null |
|
| 68 | 9 | ]); |
|
| 69 | } |
||
| 70 | |||
| 71 | /** |
||
| 72 | * @param array $params |
||
| 73 | * |
||
| 74 | * @return bool |
||
| 75 | */ |
||
| 76 | 10 | public function validateParams(array $params = []): bool |
|
| 77 | { |
||
| 78 | 10 | return ( |
|
| 79 | 10 | isset($params[ 'bucket' ]) and |
|
| 80 | 10 | isset($params[ 'key' ]) and |
|
| 81 | 10 | isset($params[ 'source' ]) |
|
| 82 | 10 | ); |
|
| 83 | } |
||
| 84 | |||
| 85 | /** |
||
| 86 | * @param string $bucketName |
||
| 87 | * @param string $keyName |
||
| 88 | * @param string $source |
||
| 89 | * @param array $params |
||
| 90 | * |
||
| 91 | * @return bool |
||
| 92 | * @throws Exception |
||
| 93 | */ |
||
| 94 | private function multipartUpload(string $bucketName, string $keyName, string $source, array $params = []): bool |
||
| 95 | { |
||
| 96 | $uploader = new MultipartUploader( |
||
| 97 | $this->client->getConn(), |
||
| 98 | $source, |
||
| 99 | [ |
||
| 100 | 'bucket' => $bucketName, |
||
| 101 | 'key' => $keyName, |
||
| 102 | 'before_initiate' => function (CommandInterface $command) use ($source, $params, $keyName) { |
||
| 103 | $command[ 'ContentType' ] = File::getMimeType($source); |
||
| 104 | |||
| 105 | if ((isset($params[ 'storage' ]))) { |
||
| 106 | $command[ 'StorageClass' ] = $params[ 'storage' ]; |
||
| 107 | } |
||
| 108 | |||
| 109 | if ((isset($params[ 'Metadata' ]))) { |
||
| 110 | $command[ 'Metadata' ] = $params[ 'meta' ]; |
||
| 111 | } |
||
| 112 | |||
| 113 | $command[ 'Metadata' ][ 'original_name' ] = File::getBaseName($keyName); |
||
| 114 | $command[ 'MetadataDirective' ] = 'REPLACE'; |
||
| 115 | } |
||
| 116 | ] |
||
| 117 | ); |
||
| 118 | |||
| 119 | try { |
||
| 120 | $upload = $uploader->upload(); |
||
| 121 | |||
| 122 | if (($upload instanceof ResultInterface) and $upload[ '@metadata' ][ 'statusCode' ] === 200) { |
||
| 123 | $this->commandHandlerLogger?->log($this, sprintf('File \'%s\' was successfully uploaded in \'%s\' bucket', $keyName, $bucketName)); |
||
| 124 | |||
| 125 | return true; |
||
| 126 | } |
||
| 127 | |||
| 128 | $this->commandHandlerLogger?->log($this, sprintf('Something went wrong during upload of file \'%s\' in \'%s\' bucket', $keyName, $bucketName), 'warning'); |
||
| 129 | |||
| 130 | // update cache |
||
| 131 | if ((!isset($params[ 'storage' ])) and $this->client->hasCache()) { |
||
| 132 | $version = null; |
||
| 133 | if (isset($upload[ '@metadata' ][ 'headers' ][ 'x-amz-version-id' ])) { |
||
| 134 | $version = $upload[ '@metadata' ][ 'headers' ][ 'x-amz-version-id' ]; |
||
| 135 | } |
||
| 136 | |||
| 137 | $this->client->getCache()->set($bucketName, $keyName, '', $version); |
||
| 138 | } |
||
| 139 | |||
| 140 | return false; |
||
| 141 | } catch (MultipartUploadException $e) { |
||
| 142 | $this->commandHandlerLogger?->logExceptionAndReturnFalse($e); |
||
| 143 | |||
| 144 | throw $e; |
||
| 145 | } |
||
| 146 | } |
||
| 147 | } |
||
| 148 |