/usr/share/php/Aws/S3/MultipartCopy.php is in php-aws-sdk 3.15.1-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | <?php
namespace Aws\S3;
use Aws\Multipart\AbstractUploadManager;
use Aws\ResultInterface;
use GuzzleHttp\Psr7;
class MultipartCopy extends AbstractUploadManager
{
use MultipartUploadingTrait;
/** @var string */
private $source;
/** @var ResultInterface */
private $sourceMetadata;
/**
* Creates a multipart upload for copying an S3 object.
*
* The valid configuration options are as follows:
*
* - acl: (string) ACL to set on the object being upload. Objects are
* private by default.
* - before_complete: (callable) Callback to invoke before the
* `CompleteMultipartUpload` operation. The callback should have a
* function signature like `function (Aws\Command $command) {...}`.
* - before_initiate: (callable) Callback to invoke before the
* `CreateMultipartUpload` operation. The callback should have a function
* signature like `function (Aws\Command $command) {...}`.
* - before_upload: (callable) Callback to invoke before `UploadPartCopy`
* operations. The callback should have a function signature like
* `function (Aws\Command $command) {...}`.
* - bucket: (string, required) Name of the bucket to which the object is
* being uploaded.
* - concurrency: (int, default=int(5)) Maximum number of concurrent
* `UploadPart` operations allowed during the multipart upload.
* - key: (string, required) Key to use for the object being uploaded.
* - part_size: (int, default=int(5242880)) Part size, in bytes, to use when
* doing a multipart upload. This must between 5 MB and 5 GB, inclusive.
* - state: (Aws\Multipart\UploadState) An object that represents the state
* of the multipart upload and that is used to resume a previous upload.
* When this option is provided, the `bucket`, `key`, and `part_size`
* options are ignored.
* - source_metadata: (Aws\ResultInterface) An object that represents the
* result of executing a HeadObject command on the copy source.
*
* @param S3Client $client Client used for the upload.
* @param string $source Location of the data to be copied
* (in the form /<bucket>/<key>).
* @param array $config Configuration used to perform the upload.
*/
public function __construct(S3Client $client, $source, array $config = [])
{
$this->source = '/' . ltrim($source, '/');
parent::__construct($client, array_change_key_case($config) + [
'source_metadata' => null
]);
}
/**
* An alias of the self::upload method.
*
* @see self::upload
*/
public function copy()
{
return $this->upload();
}
protected function loadUploadWorkflowInfo()
{
return [
'command' => [
'initiate' => 'CreateMultipartUpload',
'upload' => 'UploadPartCopy',
'complete' => 'CompleteMultipartUpload',
],
'id' => [
'bucket' => 'Bucket',
'key' => 'Key',
'upload_id' => 'UploadId',
],
'part_num' => 'PartNumber',
];
}
protected function getUploadCommands(callable $resultHandler)
{
$parts = ceil($this->getSourceSize() / $this->determinePartSize());
for ($partNumber = 1; $partNumber <= $parts; $partNumber++) {
// If we haven't already uploaded this part, yield a new part.
if (!$this->state->hasPartBeenUploaded($partNumber)) {
$command = $this->client->getCommand(
$this->info['command']['upload'],
$this->createPart($partNumber, $parts)
+ $this->getState()->getId()
);
$command->getHandlerList()->appendSign($resultHandler, 'mup');
yield $command;
}
}
}
private function createPart($partNumber, $partsCount)
{
$defaultPartSize = $this->determinePartSize();
$startByte = $defaultPartSize * ($partNumber - 1);
$partSize = $partNumber < $partsCount
? $defaultPartSize
: $this->getSourceSize() - ($defaultPartSize * ($partsCount - 1));
$endByte = $startByte + $partSize - 1;
return [
'ContentLength' => $partSize,
'CopySource' => $this->source,
'CopySourceRange' => "bytes=$startByte-$endByte",
'PartNumber' => $partNumber,
];
}
protected function extractETag(ResultInterface $result)
{
return $result->search('CopyPartResult.ETag');
}
protected function getSourceMimeType()
{
return $this->getSourceMetadata()['ContentType'];
}
protected function getSourceSize()
{
return $this->getSourceMetadata()['ContentLength'];
}
private function getSourceMetadata()
{
if (empty($this->sourceMetadata)) {
$this->sourceMetadata = $this->fetchSourceMetadata();
}
return $this->sourceMetadata;
}
private function fetchSourceMetadata()
{
if ($this->config['source_metadata'] instanceof ResultInterface) {
return $this->config['source_metadata'];
}
list($bucket, $key) = explode('/', ltrim($this->source, '/'), 2);
$headParams = [
'Bucket' => $bucket,
'Key' => $key,
];
if (strpos($key, '?')) {
list($key, $query) = explode('?', $key, 2);
$headParams['Key'] = $key;
$query = Psr7\parse_query($query, false);
if (isset($query['versionId'])) {
$headParams['VersionId'] = $query['versionId'];
}
}
return $this->client->headObject($headParams);
}
}
|