| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 | 
							- <?php
 
- namespace Qcloud\Cos;
 
- use GuzzleHttp\Psr7\Request;
 
- use GuzzleHttp\Pool;
 
- class Copy {
 
-     const MIN_PART_SIZE = 1048576;
 
-     const MAX_PART_SIZE = 5368709120;
 
-     const DEFAULT_PART_SIZE = 52428800;
 
-     const MAX_PARTS     = 10000;
 
-     private $client;
 
-     private $copySource;
 
-     private $options;
 
-     private $partSize;
 
-     private $parts;
 
-     private $size;
 
-     private $commandList = [];
 
-     private $requestList = [];
 
-     public function __construct($client, $source, $options = array()) {
 
-         $minPartSize = $options['PartSize'];
 
-         unset($options['PartSize']);
 
-         $this->client = $client;
 
-         $this->copySource = $source;
 
-         $this->options = $options;
 
-         $this->size = $source['ContentLength'];
 
-         unset($source['ContentLength']);
 
-         $this->partSize = $this->calculatePartSize($minPartSize);
 
-         $this->concurrency = isset($options['Concurrency']) ? $options['Concurrency'] : 10;
 
-         $this->retry = isset($options['Retry']) ? $options['Retry'] : 5;
 
-     }
 
-     public function copy() {
 
-         $uploadId= $this->initiateMultipartUpload();
 
-         for ($i = 0; $i < $this->retry; $i += 1) {
 
-             $rt = $this->uploadParts($uploadId);
 
-             if ($rt == 0) {
 
-                 break;
 
-             }
 
-             sleep(1 << $i);
 
-         }
 
-         foreach ( $this->parts as $key => $row ){
 
-             $num1[$key] = $row ['PartNumber'];
 
-             $num2[$key] = $row ['ETag'];
 
-         }
 
-         array_multisort($num1, SORT_ASC, $num2, SORT_ASC, $this->parts);
 
-         return $this->client->completeMultipartUpload(array(
 
-             'Bucket' => $this->options['Bucket'],
 
-             'Key' => $this->options['Key'],
 
-             'UploadId' => $uploadId,
 
-             'Parts' => $this->parts)
 
-         );
 
-     }
 
-     public function uploadParts($uploadId) {
 
-         $copyRequests = function ($uploadId) {
 
-             $offset = 0;
 
-             $partNumber = 1;
 
-             $partSize = $this->partSize;
 
-             $finishedNum = 0;
 
-             $this->parts = array();
 
-             for ($index = 1; ; $index ++) {
 
-                 if ($offset + $partSize  >= $this->size)
 
-                 {
 
-                     $partSize = $this->size - $offset;
 
-                 }
 
-                 $copySourcePath = $this->copySource['Bucket']. '.cos.'. $this->copySource['Region'].
 
-                     ".myqcloud.com/". $this->copySource['Key']. "?versionId=". $this->copySource['VersionId'];
 
-                 $params = array(
 
-                     'Bucket' => $this->options['Bucket'],
 
-                     'Key' => $this->options['Key'],
 
-                     'UploadId' => $uploadId,
 
-                     'PartNumber' => $partNumber,
 
-                     'CopySource'=> $copySourcePath,
 
-                     'CopySourceRange' => 'bytes='.((string)$offset).'-'.(string)($offset+$partSize - 1),
 
-                 );
 
-                 if(!isset($this->parts[$partNumber])) {
 
-                     $command = $this->client->getCommand('uploadPartCopy', $params);
 
-                     $request = $this->client->commandToRequestTransformer($command);
 
-                     $this->commandList[$index] = $command;
 
-                     $this->requestList[$index] = $request;
 
-                     yield $request;
 
-                 }
 
-                 ++$partNumber;
 
-                 $offset += $partSize;
 
-                 if ($this->size == $offset) {
 
-                     break;
 
-                 }
 
-             }
 
-         };
 
-         $pool = new Pool($this->client->httpClient, $copyRequests($uploadId), [
 
-             'concurrency' => $this->concurrency,
 
-             'fulfilled' => function ($response, $index) {
 
-                 $index = $index + 1;
 
-                 $response = $this->client->responseToResultTransformer($response, $this->requestList[$index], $this->commandList[$index]);
 
-                 $part = array('PartNumber' => $index, 'ETag' => $response['ETag']);
 
-                 $this->parts[$index] = $part;
 
-             },
 
-            
 
-             'rejected' => function ($reason, $index) { 
 
-                 $index = $index += 1;
 
-                 $retry = 2;
 
-                 for ($i = 1; $i <= $retry; $i++) {
 
-                     try {
 
-                         $rt =$this->client->execute($this->commandList[$index]);
 
-                         $part = array('PartNumber' => $index, 'ETag' => $rt['ETag']);
 
-                         $this->parts[$index] = $part;
 
-                     } catch(\Exception $e) {
 
-                         if ($i == $retry) {
 
-                             throw($e);
 
-                         }
 
-                     }
 
-                 }
 
-             },
 
-         ]);
 
-         
 
-         // Initiate the transfers and create a promise
 
-         $promise = $pool->promise();
 
-         
 
-         // Force the pool of requests to complete.
 
-         $promise->wait();
 
-     }
 
-     private function calculatePartSize($minPartSize)
 
-     {
 
-         $partSize = intval(ceil(($this->size / self::MAX_PARTS)));
 
-         $partSize = max($minPartSize, $partSize);
 
-         $partSize = min($partSize, self::MAX_PART_SIZE);
 
-         $partSize = max($partSize, self::MIN_PART_SIZE);
 
-         return $partSize;
 
-     }
 
-     private function initiateMultipartUpload() {
 
-         $result = $this->client->createMultipartUpload($this->options);
 
-         return $result['UploadId'];
 
-     }
 
- }
 
 
  |