Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
namespace Aws\S3;
3
 
4
use Aws\HashingStream;
5
use Aws\Multipart\AbstractUploader;
6
use Aws\PhpHash;
7
use Aws\ResultInterface;
8
use GuzzleHttp\Psr7;
9
use Psr\Http\Message\StreamInterface as Stream;
10
use Aws\S3\Exception\S3MultipartUploadException;
11
 
12
/**
13
 * Encapsulates the execution of a multipart upload to S3 or Glacier.
14
 */
15
class MultipartUploader extends AbstractUploader
16
{
17
    use MultipartUploadingTrait;
18
 
19
    const PART_MIN_SIZE = 5242880;
20
    const PART_MAX_SIZE = 5368709120;
21
    const PART_MAX_NUM = 10000;
22
 
23
    /**
24
     * Creates a multipart upload for an S3 object.
25
     *
26
     * The valid configuration options are as follows:
27
     *
28
     * - acl: (string) ACL to set on the object being upload. Objects are
29
     *   private by default.
30
     * - before_complete: (callable) Callback to invoke before the
31
     *   `CompleteMultipartUpload` operation. The callback should have a
32
     *   function signature like `function (Aws\Command $command) {...}`.
33
     * - before_initiate: (callable) Callback to invoke before the
34
     *   `CreateMultipartUpload` operation. The callback should have a function
35
     *   signature like `function (Aws\Command $command) {...}`.
36
     * - before_upload: (callable) Callback to invoke before any `UploadPart`
37
     *   operations. The callback should have a function signature like
38
     *   `function (Aws\Command $command) {...}`.
39
     * - bucket: (string, required) Name of the bucket to which the object is
40
     *   being uploaded, or an S3 access point ARN.
41
     * - concurrency: (int, default=int(5)) Maximum number of concurrent
42
     *   `UploadPart` operations allowed during the multipart upload.
43
     * - key: (string, required) Key to use for the object being uploaded.
44
     * - params: (array) An array of key/value parameters that will be applied
45
     *   to each of the sub-commands run by the uploader as a base.
46
     *   Auto-calculated options will override these parameters. If you need
47
     *   more granularity over parameters to each sub-command, use the before_*
48
     *   options detailed above to update the commands directly.
49
     * - part_size: (int, default=int(5242880)) Part size, in bytes, to use when
50
     *   doing a multipart upload. This must between 5 MB and 5 GB, inclusive.
51
     * - prepare_data_source: (callable) Callback to invoke before starting the
52
     *   multipart upload workflow. The callback should have a function
53
     *   signature like `function () {...}`.
54
     * - state: (Aws\Multipart\UploadState) An object that represents the state
55
     *   of the multipart upload and that is used to resume a previous upload.
56
     *   When this option is provided, the `bucket`, `key`, and `part_size`
57
     *   options are ignored.
58
     *
59
     * @param S3ClientInterface $client Client used for the upload.
60
     * @param mixed             $source Source of the data to upload.
61
     * @param array             $config Configuration used to perform the upload.
62
     */
63
    public function __construct(
64
        S3ClientInterface $client,
65
        $source,
66
        array $config = []
67
    ) {
68
        parent::__construct($client, $source, array_change_key_case($config) + [
69
            'bucket' => null,
70
            'key'    => null,
71
            'exception_class' => S3MultipartUploadException::class,
72
        ]);
73
    }
74
 
75
    protected function loadUploadWorkflowInfo()
76
    {
77
        return [
78
            'command' => [
79
                'initiate' => 'CreateMultipartUpload',
80
                'upload'   => 'UploadPart',
81
                'complete' => 'CompleteMultipartUpload',
82
            ],
83
            'id' => [
84
                'bucket'    => 'Bucket',
85
                'key'       => 'Key',
86
                'upload_id' => 'UploadId',
87
            ],
88
            'part_num' => 'PartNumber',
89
        ];
90
    }
91
 
92
    protected function createPart($seekable, $number)
93
    {
94
        // Initialize the array of part data that will be returned.
95
        $data = [];
96
 
97
        // Apply custom params to UploadPart data
98
        $config = $this->getConfig();
99
        $params = isset($config['params']) ? $config['params'] : [];
100
        foreach ($params as $k => $v) {
101
            $data[$k] = $v;
102
        }
103
 
104
        $data['PartNumber'] = $number;
105
 
106
        // Read from the source to create the body stream.
107
        if ($seekable) {
108
            // Case 1: Source is seekable, use lazy stream to defer work.
109
            $body = $this->limitPartStream(
110
                new Psr7\LazyOpenStream($this->source->getMetadata('uri'), 'r')
111
            );
112
        } else {
113
            // Case 2: Stream is not seekable; must store in temp stream.
114
            $source = $this->limitPartStream($this->source);
115
            $source = $this->decorateWithHashes($source, $data);
116
            $body = Psr7\Utils::streamFor();
117
            Psr7\Utils::copyToStream($source, $body);
118
        }
119
 
120
        $contentLength = $body->getSize();
121
 
122
        // Do not create a part if the body size is zero.
123
        if ($contentLength === 0) {
124
            return false;
125
        }
126
 
127
        $body->seek(0);
128
        $data['Body'] = $body;
129
 
130
        if (isset($config['add_content_md5'])
131
            && $config['add_content_md5'] === true
132
        ) {
133
            $data['AddContentMD5'] = true;
134
        }
135
 
136
        $data['ContentLength'] = $contentLength;
137
 
138
        return $data;
139
    }
140
 
141
    protected function extractETag(ResultInterface $result)
142
    {
143
        return $result['ETag'];
144
    }
145
 
146
    protected function getSourceMimeType()
147
    {
148
        if ($uri = $this->source->getMetadata('uri')) {
149
            return Psr7\MimeType::fromFilename($uri)
150
                ?: 'application/octet-stream';
151
        }
152
    }
153
 
154
    protected function getSourceSize()
155
    {
156
        return $this->source->getSize();
157
    }
158
 
159
    /**
160
     * Decorates a stream with a sha256 linear hashing stream.
161
     *
162
     * @param Stream $stream Stream to decorate.
163
     * @param array  $data   Part data to augment with the hash result.
164
     *
165
     * @return Stream
166
     */
167
    private function decorateWithHashes(Stream $stream, array &$data)
168
    {
169
        // Decorate source with a hashing stream
170
        $hash = new PhpHash('sha256');
171
        return new HashingStream($stream, $hash, function ($result) use (&$data) {
172
            $data['ContentSHA256'] = bin2hex($result);
173
        });
174
    }
175
}