You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
249 lines
9.8 KiB
PHTML
249 lines
9.8 KiB
PHTML
5 years ago
|
<?php
|
||
|
|
||
|
namespace Qcloud\Cos;
|
||
|
|
||
|
use Guzzle\Service\Description\Parameter;
|
||
|
use Guzzle\Service\Description\ServiceDescription;
|
||
|
use Guzzle\Service\Client as GSClient;
|
||
|
use Guzzle\Common\Collection;
|
||
|
use Guzzle\Http\EntityBody;
|
||
|
use Guzzle\Http\Message\RequestInterface;
|
||
|
use Qcloud\Cos\Signature;
|
||
|
use Qcloud\Cos\TokenListener;
|
||
|
|
||
|
class Client extends GSClient {
|
||
|
const VERSION = '1.3.1';
|
||
|
|
||
|
private $region; // string: region.
|
||
|
private $credentials;
|
||
|
private $appId; // string: application id.
|
||
|
private $secretId; // string: secret id.
|
||
|
private $secretKey; // string: secret key.
|
||
|
private $timeout; // int: timeout
|
||
|
private $connect_timeout; // int: connect_timeout
|
||
|
private $signature;
|
||
|
private $schema;
|
||
|
private $ip;
|
||
|
private $port;
|
||
|
|
||
|
|
||
|
public function __construct($config) {
|
||
|
$this->region = $config['region'];
|
||
|
$regionmap = array('cn-east'=>'ap-shanghai',
|
||
|
'cn-south'=>'ap-guangzhou',
|
||
|
'cn-north'=>'ap-beijing-1',
|
||
|
'cn-south-2'=>'ap-guangzhou-2',
|
||
|
'cn-southwest'=>'ap-chengdu',
|
||
|
'sg'=>'ap-singapore',
|
||
|
'tj'=>'ap-beijing-1',
|
||
|
'bj'=>'ap-beijing',
|
||
|
'sh'=>'ap-shanghai',
|
||
|
'gz'=>'ap-guangzhou',
|
||
|
'cd'=>'ap-chengdu',
|
||
|
'sgp'=>'ap-singapore',);
|
||
|
$this->schema = isset($config['schema']) ? $config['schema'] : 'http';
|
||
|
$this->ip = isset($config['ip']) ? $config['ip'] : null;
|
||
|
$this->port = isset($config['port']) ? $config['port'] : null;
|
||
|
$this->region = isset($regionmap[$this->region]) ? $regionmap[$this->region] : $this->region;
|
||
|
$this->credentials = $config['credentials'];
|
||
|
$this->appId = isset($config['credentials']['appId']) ? $config['credentials']['appId'] : null;
|
||
|
$this->secretId = $config['credentials']['secretId'];
|
||
|
$this->secretKey = $config['credentials']['secretKey'];
|
||
|
$this->token = isset($config['credentials']['token']) ? $config['credentials']['token'] : null;
|
||
|
$this->timeout = isset($config['timeout']) ? $config['timeout'] : 3600;
|
||
|
$this->connect_timeout = isset($config['connect_timeout']) ? $config['connect_timeout'] : 3600;
|
||
|
$this->signature = new signature($this->secretId, $this->secretKey);
|
||
|
parent::__construct(
|
||
|
$this->schema.'://cos.' . $this->region . '.myqcloud.com/', // base url
|
||
|
array('request.options' => array('timeout' => $this->timeout, 'connect_timeout' => $this->connect_timeout),
|
||
|
)); // show curl verbose or not
|
||
|
$desc = ServiceDescription::factory(Service::getService());
|
||
|
$this->setDescription($desc);
|
||
|
$this->setUserAgent('cos-php-sdk-v5.' . Client::VERSION, true);
|
||
|
$this->addSubscriber(new ExceptionListener());
|
||
|
$this->addSubscriber(new Md5Listener($this->signature));
|
||
|
$this->addSubscriber(new TokenListener($this->token));
|
||
|
$this->addSubscriber(new SignatureListener($this->secretId, $this->secretKey));
|
||
|
$this->addSubscriber(new BucketStyleListener($this->appId, $this->ip, $this->port));
|
||
|
// Allow for specifying bodies with file paths and file handles
|
||
|
$this->addSubscriber(new UploadBodyListener(array('PutObject', 'UploadPart')));
|
||
|
}
|
||
|
|
||
|
public function __destruct() {
|
||
|
}
|
||
|
|
||
|
public function __call($method, $args) {
|
||
|
return parent::__call(ucfirst($method), $args);
|
||
|
}
|
||
|
|
||
|
public function createAuthorization(RequestInterface $request, $expires)
|
||
|
{
|
||
|
if ($request->getClient() !== $this) {
|
||
|
throw new InvalidArgumentException('The request object must be associated with the client. Use the '
|
||
|
. '$client->get(), $client->head(), $client->post(), $client->put(), etc. methods when passing in a '
|
||
|
. 'request object');
|
||
|
}
|
||
|
return $this->signature->createAuthorization($request, $expires);
|
||
|
}
|
||
|
public function createPresignedUrl(RequestInterface $request, $expires)
|
||
|
{
|
||
|
if ($request->getClient() !== $this) {
|
||
|
throw new InvalidArgumentException('The request object must be associated with the client. Use the '
|
||
|
. '$client->get(), $client->head(), $client->post(), $client->put(), etc. methods when passing in a '
|
||
|
. 'request object');
|
||
|
}
|
||
|
return $this->signature->createPresignedUrl($request, $expires);
|
||
|
}
|
||
|
public function getObjectUrl($bucket, $key, $expires = null, array $args = array())
|
||
|
{
|
||
|
$command = $this->getCommand('GetObject', $args + array('Bucket' => $bucket, 'Key' => $key));
|
||
|
|
||
|
if ($command->hasKey('Scheme')) {
|
||
|
$scheme = $command['Scheme'];
|
||
|
$request = $command->remove('Scheme')->prepare()->setScheme($scheme)->setPort(null);
|
||
|
} else {
|
||
|
$request = $command->prepare();
|
||
|
}
|
||
|
|
||
|
return $expires ? $this->createPresignedUrl($request, $expires) : $request->getUrl();
|
||
|
}
|
||
|
public function Upload($bucket, $key, $body, $options = array()) {
|
||
|
$body = EntityBody::factory($body);
|
||
|
$options = Collection::fromConfig(array_change_key_case($options), array(
|
||
|
'min_part_size' => MultipartUpload::MIN_PART_SIZE,
|
||
|
'params' => $options));
|
||
|
if ($body->getSize() < $options['min_part_size']) {
|
||
|
// Perform a simple PutObject operation
|
||
|
$rt = $this->putObject(array(
|
||
|
'Bucket' => $bucket,
|
||
|
'Key' => $key,
|
||
|
'Body' => $body,
|
||
|
) + $options['params']);
|
||
|
|
||
|
$rt['Location'] = $rt['ObjectURL'];
|
||
|
unset($rt['ObjectURL']);
|
||
|
}
|
||
|
else {
|
||
|
$multipartUpload = new MultipartUpload($this, $body, $options['min_part_size'], array(
|
||
|
'Bucket' => $bucket,
|
||
|
'Key' => $key,
|
||
|
'Body' => $body,
|
||
|
) + $options['params']);
|
||
|
|
||
|
$rt = $multipartUpload->performUploading();
|
||
|
}
|
||
|
return $rt;
|
||
|
}
|
||
|
|
||
|
public function resumeUpload($bucket, $key, $body, $uploadId, $options = array()) {
|
||
|
$body = EntityBody::factory($body);
|
||
|
$options = Collection::fromConfig(array_change_key_case($options), array(
|
||
|
'min_part_size' => MultipartUpload::MIN_PART_SIZE,
|
||
|
'params' => $options));
|
||
|
$multipartUpload = new MultipartUpload($this, $body, $options['min_part_size'], array(
|
||
|
'Bucket' => $bucket,
|
||
|
'Key' => $key,
|
||
|
'Body' => $body,
|
||
|
'UploadId' => $uploadId,
|
||
|
) + $options['params']);
|
||
|
|
||
|
$rt = $multipartUpload->resumeUploading();
|
||
|
return $rt;
|
||
|
}
|
||
|
|
||
|
public function Copy($bucket, $key, $copysource, $options = array()) {
|
||
|
|
||
|
$options = Collection::fromConfig(array_change_key_case($options), array(
|
||
|
'min_part_size' => Copy::MIN_PART_SIZE,
|
||
|
'params' => $options));
|
||
|
$sourcelistdot = explode('.',$copysource);
|
||
|
$sourcelistline = explode('-',$sourcelistdot[0]);
|
||
|
$sourceappid = array_pop($sourcelistline);
|
||
|
$sourcebucket = implode('-', $sourcelistline);
|
||
|
$sourceregion = $sourcelistdot[2];
|
||
|
$sourcekey = substr(strstr($copysource,'/'),1);
|
||
|
$sourceversion = "";
|
||
|
$cosClient = new Client(array('region' => $sourceregion,
|
||
|
'credentials'=> array(
|
||
|
'appId' => $sourceappid,
|
||
|
'secretId' => $this->secretId,
|
||
|
'secretKey' => $this->secretKey)));
|
||
|
if (!key_exists('VersionId',$options['params'])) {
|
||
|
$sourceversion = "";
|
||
|
}
|
||
|
else {
|
||
|
$sourceversion = $options['params']['VersionId'];
|
||
|
}
|
||
|
$rt = $cosClient->headObject(array('Bucket'=>$sourcebucket,
|
||
|
'Key'=>$sourcekey,
|
||
|
'VersionId'=>$sourceversion));
|
||
|
$contentlength =$rt['ContentLength'];
|
||
|
|
||
|
if ($contentlength < $options['min_part_size']) {
|
||
|
return $this->copyObject(array(
|
||
|
'Bucket' => $bucket,
|
||
|
'Key' => $key,
|
||
|
'CopySource' => $copysource."?versionId=".$sourceversion,
|
||
|
) + $options['params']);
|
||
|
}
|
||
|
$copy = new Copy($this, $contentlength, $copysource."?versionId=".$sourceversion, $options['min_part_size'], array(
|
||
|
'Bucket' => $bucket,
|
||
|
'Key' => $key
|
||
|
) + $options['params']);
|
||
|
|
||
|
return $copy->copy();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Determines whether or not a bucket exists by name
|
||
|
*
|
||
|
* @param string $bucket The name of the bucket
|
||
|
* @param bool $accept403 Set to true if 403s are acceptable
|
||
|
* @param array $options Additional options to add to the executed command
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function doesBucketExist($bucket, $accept403 = true, array $options = array())
|
||
|
{
|
||
|
try {
|
||
|
$this->HeadBucket(array(
|
||
|
'Bucket' => $bucket));
|
||
|
return True;
|
||
|
}catch (\Exception $e){
|
||
|
return False;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Determines whether or not an object exists by name
|
||
|
*
|
||
|
* @param string $bucket The name of the bucket
|
||
|
* @param string $key The key of the object
|
||
|
* @param array $options Additional options to add to the executed command
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function doesObjectExist($bucket, $key, array $options = array())
|
||
|
{
|
||
|
try {
|
||
|
$this->HeadObject(array(
|
||
|
'Bucket' => $bucket,
|
||
|
'Key' => $key));
|
||
|
return True;
|
||
|
}catch (\Exception $e){
|
||
|
return False;
|
||
|
}
|
||
|
}
|
||
|
public static function encodeKey($key) {
|
||
|
// return $key;
|
||
|
return str_replace('%2F', '/', rawurlencode($key));
|
||
|
}
|
||
|
|
||
|
public static function explodeKey($key) {
|
||
|
// Remove a leading slash if one is found
|
||
|
return explode('/', $key && $key[0] == '/' ? substr($key, 1) : $key);
|
||
|
// return $key;
|
||
|
// return ltrim($key, "/");
|
||
|
}
|
||
|
}
|