EVOLUTION-MANAGER
Edit File: UploadBuilder.php
<?php /** * Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ namespace DuplicatorPro\Aws\S3\Model\MultipartUpload; defined("ABSPATH") or die(""); use DuplicatorPro\Aws\Common\Enum\UaString as Ua; use DuplicatorPro\Aws\Common\Exception\InvalidArgumentException; use DuplicatorPro\Aws\Common\Model\MultipartUpload\AbstractUploadBuilder; use DuplicatorPro\Aws\S3\Model\Acp; /** * Easily create a multipart uploader used to quickly and reliably upload a * large file or data stream to Amazon S3 using multipart uploads */ class UploadBuilder extends AbstractUploadBuilder { /** * @var int Concurrency level to transfer the parts */ protected $concurrency = 1; /** * @var int Minimum part size to upload */ protected $minPartSize = AbstractTransfer::MIN_PART_SIZE; /** * @var string MD5 hash of the entire body to transfer */ protected $md5; /** * @var bool Whether or not to calculate the entire MD5 hash of the object */ protected $calculateEntireMd5 = false; /** * @var bool Whether or not to calculate MD5 hash of each part */ protected $calculatePartMd5 = true; /** * @var array Array of initiate command options */ protected $commandOptions = array(); /** * @var array Array of transfer options */ protected $transferOptions = array(); /** * Set the bucket to upload the object to * * @param string $bucket Name of the bucket * * @return $this */ public function setBucket($bucket) { return $this->setOption('Bucket', $bucket); } /** * Set the key of the object * * @param string $key Key of the object to upload * * @return $this */ public function setKey($key) { return $this->setOption('Key', $key); } /** * Set the minimum acceptable part size * * @param int $minSize Minimum acceptable part size in bytes * * @return $this */ public function setMinPartSize($minSize) { $this->minPartSize = (int) max((int) $minSize, AbstractTransfer::MIN_PART_SIZE); return $this; } /** * Set the concurrency level to use when uploading parts. This affects how * many parts are uploaded in parallel. You must use a local file as your * data source when using a concurrency greater than 1 * * @param int $concurrency Concurrency level * * @return $this */ public function setConcurrency($concurrency) { $this->concurrency = $concurrency; return $this; } /** * Explicitly set the MD5 hash of the entire body * * @param string $md5 MD5 hash of the entire body * * @return $this */ public function setMd5($md5) { $this->md5 = $md5; return $this; } /** * Set to true to have the builder calculate the MD5 hash of the entire data * source before initiating a multipart upload (this could be an expensive * operation). This setting can ony be used with seekable data sources. * * @param bool $calculateMd5 Set to true to calculate the MD5 hash of the body * * @return $this */ public function calculateMd5($calculateMd5) { $this->calculateEntireMd5 = (bool) $calculateMd5; return $this; } /** * Specify whether or not to calculate the MD5 hash of each uploaded part. * This setting defaults to true. * * @param bool $usePartMd5 Set to true to calculate the MD5 has of each part * * @return $this */ public function calculatePartMd5($usePartMd5) { $this->calculatePartMd5 = (bool) $usePartMd5; return $this; } /** * Set the ACP to use on the object * * @param Acp $acp ACP to set on the object * * @return $this */ public function setAcp(Acp $acp) { return $this->setOption('ACP', $acp); } /** * Set an option to pass to the initial CreateMultipartUpload operation * * @param string $name Option name * @param string $value Option value * * @return $this */ public function setOption($name, $value) { $this->commandOptions[$name] = $value; return $this; } /** * Add an array of options to pass to the initial CreateMultipartUpload operation * * @param array $options Array of CreateMultipartUpload operation parameters * * @return $this */ public function addOptions(array $options) { $this->commandOptions = array_replace($this->commandOptions, $options); return $this; } /** * Set an array of transfer options to apply to the upload transfer object * * @param array $options Transfer options * * @return $this */ public function setTransferOptions(array $options) { $this->transferOptions = $options; return $this; } /** * {@inheritdoc} * @throws InvalidArgumentException when attempting to resume a transfer using a non-seekable stream * @throws InvalidArgumentException when missing required properties (bucket, key, client, source) */ public function build() { if ($this->state instanceof TransferState) { $this->commandOptions = array_replace($this->commandOptions, $this->state->getUploadId()->toParams()); } if (!isset($this->commandOptions['Bucket']) || !isset($this->commandOptions['Key']) || !$this->client || !$this->source ) { throw new InvalidArgumentException('You must specify a Bucket, Key, client, and source.'); } if ($this->state && !$this->source->isSeekable()) { throw new InvalidArgumentException('You cannot resume a transfer using a non-seekable source.'); } // If no state was set, then create one by initiating or loading a multipart upload if (is_string($this->state)) { $this->state = TransferState::fromUploadId($this->client, UploadId::fromParams(array( 'Bucket' => $this->commandOptions['Bucket'], 'Key' => $this->commandOptions['Key'], 'UploadId' => $this->state ))); } elseif (!$this->state) { $this->state = $this->initiateMultipartUpload(); } $options = array_replace(array( 'min_part_size' => $this->minPartSize, 'part_md5' => (bool) $this->calculatePartMd5, 'concurrency' => $this->concurrency ), $this->transferOptions); return $this->concurrency > 1 ? new ParallelTransfer($this->client, $this->state, $this->source, $options) : new SerialTransfer($this->client, $this->state, $this->source, $options); } /** * {@inheritdoc} */ protected function initiateMultipartUpload() { // Determine Content-Type if (!isset($this->commandOptions['ContentType'])) { if ($mimeType = $this->source->getContentType()) { $this->commandOptions['ContentType'] = $mimeType; } } $params = array_replace(array( Ua::OPTION => Ua::MULTIPART_UPLOAD, 'command.headers' => $this->headers, 'Metadata' => array() ), $this->commandOptions); // Calculate the MD5 hash if none was set and it is asked of the builder if ($this->calculateEntireMd5) { $this->md5 = $this->source->getContentMd5(); } // If an MD5 is specified, then add it to the custom headers of the request // so that it will be returned when downloading the object from Amazon S3 if ($this->md5) { $params['Metadata']['x-amz-Content-MD5'] = $this->md5; } $result = $this->client->getCommand('CreateMultipartUpload', $params)->execute(); // Create a new state based on the initiated upload $params['UploadId'] = $result['UploadId']; return new TransferState(UploadId::fromParams($params)); } }