<?php 
namespace Aws\S3; 
 
use Aws\CommandInterface; 
use Aws\Multipart\UploadState; 
use Aws\ResultInterface; 
 
trait MultipartUploadingTrait 
{ 
    /** 
     * Creates an UploadState object for a multipart upload by querying the 
     * service for the specified upload's information. 
     * 
     * @param S3Client $client   S3Client used for the upload. 
     * @param string   $bucket   Bucket for the multipart upload. 
     * @param string   $key      Object key for the multipart upload. 
     * @param string   $uploadId Upload ID for the multipart upload. 
     * 
     * @return UploadState 
     */ 
    public static function getStateFromService( 
        S3Client $client, 
        $bucket, 
        $key, 
        $uploadId 
    ) { 
        $state = new UploadState([ 
            'Bucket'   => $bucket, 
            'Key'      => $key, 
            'UploadId' => $uploadId, 
        ]); 
 
        foreach ($client->getPaginator('ListParts', $state->getId()) as $result) { 
            // Get the part size from the first part in the first result. 
            if (!$state->getPartSize()) { 
                $state->setPartSize($result->search('Parts[0].Size')); 
            } 
            // Mark all the parts returned by ListParts as uploaded. 
            foreach ($result['Parts'] as $part) { 
                $state->markPartAsUploaded($part['PartNumber'], [ 
                    'PartNumber' => $part['PartNumber'], 
                    'ETag'       => $part['ETag'] 
                ]); 
            } 
        } 
 
        $state->setStatus(UploadState::INITIATED); 
 
        return $state; 
    } 
 
    protected function handleResult(CommandInterface $command, ResultInterface $result) 
    { 
        $this->getState()->markPartAsUploaded($command['PartNumber'], [ 
            'PartNumber' => $command['PartNumber'], 
            'ETag'       => $this->extractETag($result), 
        ]); 
    } 
 
    abstract protected function extractETag(ResultInterface $result); 
 
    protected function getCompleteParams() 
    { 
        return ['MultipartUpload' => [ 
            'Parts' => $this->getState()->getUploadedParts() 
        ]]; 
    } 
 
    protected function determinePartSize() 
    { 
        // Make sure the part size is set. 
        $partSize = $this->getConfig()['part_size'] ?: MultipartUploader::PART_MIN_SIZE; 
 
        // Adjust the part size to be larger for known, x-large uploads. 
        if ($sourceSize = $this->getSourceSize()) { 
            $partSize = (int) max( 
                $partSize, 
                ceil($sourceSize / MultipartUploader::PART_MAX_NUM) 
            ); 
        } 
 
        // Ensure that the part size follows the rules: 5 MB <= size <= 5 GB. 
        if ($partSize < MultipartUploader::PART_MIN_SIZE || $partSize > MultipartUploader::PART_MAX_SIZE) { 
            throw new \InvalidArgumentException('The part size must be no less ' 
                . 'than 5 MB and no greater than 5 GB.'); 
        } 
 
        return $partSize; 
    } 
 
    protected function getInitiateParams() 
    { 
        $params = []; 
 
        if (isset($this->getConfig()['acl'])) { 
            $params['ACL'] = $this->getConfig()['acl']; 
        } 
 
        // Set the content type 
        if ($type = $this->getSourceMimeType()) { 
            $params['ContentType'] = $type; 
        } 
 
        return $params; 
    } 
 
    /** 
     * @return UploadState 
     */ 
    abstract protected function getState(); 
 
    /** 
     * @return array 
     */ 
    abstract protected function getConfig(); 
 
    /** 
     * @return int 
     */ 
    abstract protected function getSourceSize(); 
 
    /** 
     * @return string|null 
     */ 
    abstract protected function getSourceMimeType(); 
} 
 
 |