Issues (21)

src/Commands/Handlers/UploadItem.php (1 issue)

Labels
Severity
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
A parse error occurred: Syntax error, unexpected T_STRING, expecting '=' on line 28 at column 14
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