初始化代码
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace Qcloud\Cos;
|
||||
|
||||
use Guzzle\Common\Event;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Change from path style to host style, currently only host style is supported in cos.
|
||||
*/
|
||||
function endWith($haystack, $needle) {
|
||||
$length = strlen($needle);
|
||||
if($length == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return (substr($haystack, -$length) === $needle);
|
||||
}
|
||||
class BucketStyleListener implements EventSubscriberInterface {
|
||||
|
||||
private $appId; // string: application id.
|
||||
|
||||
public function __construct($appId) {
|
||||
$this->appId = $appId;
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents() {
|
||||
return array('command.after_prepare' => array('onCommandAfterPrepare', -230));
|
||||
}
|
||||
|
||||
/**
|
||||
* Change from path style to host style.
|
||||
* @param Event $event Event emitted.
|
||||
*/
|
||||
public function onCommandAfterPrepare(Event $event) {
|
||||
$command = $event['command'];
|
||||
$bucket = $command['Bucket'];
|
||||
$request = $command->getRequest();
|
||||
|
||||
if ($command->getName() == 'ListBuckets')
|
||||
{
|
||||
$request->setHost('service.cos.myqcloud.com');
|
||||
return ;
|
||||
}
|
||||
if ($key = $command['Key']) {
|
||||
// Modify the command Key to account for the {/Key*} explosion into an array
|
||||
if (is_array($key)) {
|
||||
$command['Key'] = $key = implode('/', $key);
|
||||
}
|
||||
}
|
||||
$request->setHeader('Date', gmdate('D, d M Y H:i:s T'));
|
||||
$request->setPath(preg_replace("#^/{$bucket}#", '', $request->getPath()));
|
||||
|
||||
if ($this->appId != null && endWith($bucket,'-'.$this->appId) == False)
|
||||
{
|
||||
$bucket = $bucket.'-'.$this->appId;
|
||||
}
|
||||
// Set the key and bucket on the request
|
||||
$request->getParams()->set('bucket', $bucket)->set('key', $key);
|
||||
|
||||
//$request->setPath(urldecode($request->getPath()));
|
||||
// Switch to virtual hosted bucket
|
||||
$request->setHost($bucket. '.' . $request->getHost());
|
||||
if (!$bucket) {
|
||||
$request->getParams()->set('cos.resource', '/');
|
||||
} else {
|
||||
// Bucket style needs a trailing slash
|
||||
$request->getParams()->set(
|
||||
'cos.resource',
|
||||
'/' . rawurlencode($bucket) . ($key ? ('/' . Client::encodeKey($key)) : '/')
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
270
app/Common/extend/tencentcloud/src/Qcloud/Cos/Client.php
Normal file
270
app/Common/extend/tencentcloud/src/Qcloud/Cos/Client.php
Normal file
@@ -0,0 +1,270 @@
|
||||
<?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.0';
|
||||
|
||||
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;
|
||||
|
||||
public function __construct($config) {
|
||||
$this->region = $config['region'];
|
||||
$regionmap = array('cn-east'=>'ap-shanghai',
|
||||
'cn-sorth'=>'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->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(
|
||||
'http://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));
|
||||
|
||||
// Allow for specifying bodies with file paths and file handles
|
||||
$this->addSubscriber(new UploadBodyListener(array('PutObject', 'UploadPart')));
|
||||
}
|
||||
public function set_config($config) {
|
||||
$this->region = $config['region'];
|
||||
$regionmap = array('cn-east'=>'ap-shanghai',
|
||||
'cn-sorth'=>'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->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(
|
||||
'http://cos.' . $this->region . '.myqcloud.com/', // base url
|
||||
array('request.options' => array('timeout' => $this->timeout, 'connect_timeout' => $this->connect_timeout),
|
||||
)); // show curl verbose or not
|
||||
}
|
||||
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, "/");
|
||||
}
|
||||
}
|
||||
39
app/Common/extend/tencentcloud/src/Qcloud/Cos/Command.php
Normal file
39
app/Common/extend/tencentcloud/src/Qcloud/Cos/Command.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Qcloud\Cos;
|
||||
|
||||
use Guzzle\Service\Command\OperationCommand;
|
||||
use Guzzle\Service\Resource\Model;
|
||||
use Guzzle\Common\Event;
|
||||
|
||||
/**
|
||||
* Adds functionality to Qcloud Cos commands:
|
||||
* - Adds the PutObject URL to a response
|
||||
* - Allows creating a Pre-signed URL from any command
|
||||
*/
|
||||
class Command extends OperationCommand {
|
||||
/**
|
||||
* Create a pre-signed URL for the operation
|
||||
*
|
||||
* @param int|string $expires The Unix timestamp to expire at or a string that can be evaluated by strtotime
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function createPresignedUrl($expires)
|
||||
{
|
||||
return $this->client->createPresignedUrl($this->prepare(), $expires);
|
||||
}
|
||||
public function createAuthorization($expires)
|
||||
{
|
||||
return $this->client->createAuthorization($this->prepare(), $expires);
|
||||
}
|
||||
|
||||
protected function process() {
|
||||
parent::process();
|
||||
// Set the GetObject URL if using the PutObject operation
|
||||
if ($this->result instanceof Model && $this->getName() == 'PutObject') {
|
||||
$request = $this->getRequest();;
|
||||
$this->result->set('ObjectURL', $request->getUrl());
|
||||
}
|
||||
}
|
||||
}
|
||||
140
app/Common/extend/tencentcloud/src/Qcloud/Cos/Copy.php
Normal file
140
app/Common/extend/tencentcloud/src/Qcloud/Cos/Copy.php
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
namespace Qcloud\Cos;
|
||||
|
||||
use Guzzle\Http\ReadLimitEntityBody;
|
||||
|
||||
|
||||
class Copy {
|
||||
/**
|
||||
* const var: part size from 5MB to 5GB, and max parts of 10000 are allowed for each upload.
|
||||
*/
|
||||
const MIN_PART_SIZE = 5242880;
|
||||
const MAX_PART_SIZE = 5368709120;
|
||||
const MAX_PARTS = 10000;
|
||||
|
||||
private $client;
|
||||
private $source;
|
||||
private $options;
|
||||
private $partSize;
|
||||
private $size;
|
||||
|
||||
public function __construct($client, $contentlength, $source, $minPartSize, $options = array()) {
|
||||
$this->client = $client;
|
||||
$this->source = $source;
|
||||
$this->options = $options;
|
||||
$this->size = $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 < 5; $i += 1) {
|
||||
$rt = $this->uploadParts($uploadId);
|
||||
if ($rt == 0) {
|
||||
break;
|
||||
}
|
||||
sleep(1 << $i);
|
||||
}
|
||||
return $this->client->completeMultipartUpload(array(
|
||||
'Bucket' => $this->options['Bucket'],
|
||||
'Key' => $this->options['Key'],
|
||||
'UploadId' => $uploadId,
|
||||
'Parts' => $this->parts));
|
||||
|
||||
}
|
||||
public function uploadParts($uploadId) {
|
||||
$commands = array();
|
||||
$offset = 0;
|
||||
$partNumber = 1;
|
||||
$partSize = $this->partSize;
|
||||
$finishedNum = 0;
|
||||
$this->parts = array();
|
||||
for (;;) {
|
||||
|
||||
if ($offset + $partSize >= $this->size)
|
||||
{
|
||||
$partSize = $this->size - $offset;
|
||||
}
|
||||
$params = array(
|
||||
'Bucket' => $this->options['Bucket'],
|
||||
'Key' => $this->options['Key'],
|
||||
'UploadId' => $uploadId,
|
||||
'PartNumber' => $partNumber,
|
||||
'CopySource'=> $this->source,
|
||||
'CopySourceRange' => 'bytes='.((string)$offset).'-'.(string)($offset+$partSize - 1),
|
||||
);
|
||||
if(!isset($parts[$partNumber])) {
|
||||
$commands[] = $this->client->getCommand('UploadPartCopy', $params);
|
||||
}
|
||||
if ($partNumber % $this->concurrency == 0) {
|
||||
$this->client->execute($commands);
|
||||
$commands = array();
|
||||
}
|
||||
++$partNumber;
|
||||
$offset += $partSize;
|
||||
if ($this->size == $offset)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!empty($commands)) {
|
||||
$this->client->execute($commands);
|
||||
}
|
||||
try {
|
||||
$marker = 0;
|
||||
$finishedNum = 1;
|
||||
while (true) {
|
||||
$rt = $this->client->listParts(array(
|
||||
'Bucket' => $this->options['Bucket'],
|
||||
'Key' => $this->options['Key'],
|
||||
'PartNumberMarker' => $marker,
|
||||
'MaxParts' => 1000,
|
||||
'UploadId' => $uploadId));
|
||||
if (!empty($rt['Parts'])) {
|
||||
foreach ($rt['Parts'] as $part) {
|
||||
$part = array('PartNumber' => $finishedNum, 'ETag' => $part['ETag']);
|
||||
$this->parts[$finishedNum] = $part;
|
||||
$finishedNum++;
|
||||
}
|
||||
}
|
||||
$marker = $rt['NextPartNumberMarker'];
|
||||
if (!$rt['IsTruncated']) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
echo($e);
|
||||
}
|
||||
if ($finishedNum == $partNumber) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
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'];
|
||||
}
|
||||
|
||||
}
|
||||
function partUploadCopy($client, $params) {
|
||||
$rt = $client->uploadPartCopy($params);
|
||||
// $part = array('PartNumber' => $params['PartNumber'], 'ETag' => $rt['ETag']);
|
||||
$rt['PartNumber'] = $params['PartNumber'];
|
||||
return $rt;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace Qcloud\Cos\Exception;
|
||||
|
||||
class BucketAlreadyExistsException extends CosException {}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Qcloud\Cos\Exception;
|
||||
|
||||
// The bucket you tried to delete is not empty.
|
||||
class BucketNotEmptyException extends CosException {}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Qcloud\Cos\Exception;
|
||||
|
||||
use Qcloud\Cos\Exception\ServiceResponseException;
|
||||
|
||||
class CosException extends ServiceResponseException {}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace Qcloud\Cos\Exception;
|
||||
|
||||
class CurlException extends CosException {}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace Qcloud\Cos\Exception;
|
||||
|
||||
class InvalidArgumentException extends CosException {}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Qcloud\Cos\Exception;
|
||||
|
||||
// The specified bucket does not exist.
|
||||
class NoSuchBucketException extends CosException {}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Qcloud\Cos\Exception;
|
||||
|
||||
// The specified key does not exist.
|
||||
class NoSuchKeyException extends CosException {}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Qcloud\Cos\Exception;
|
||||
|
||||
/**
|
||||
* The specified multipart upload does not exist.
|
||||
*/
|
||||
class NoSuchUploadException extends CosException {}
|
||||
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
|
||||
namespace Qcloud\Cos\Exception;
|
||||
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
use Guzzle\Http\Message\Response;
|
||||
|
||||
class ServiceResponseException extends \RuntimeException {
|
||||
|
||||
/**
|
||||
* @var Response Response
|
||||
*/
|
||||
protected $response;
|
||||
|
||||
/**
|
||||
* @var RequestInterface Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* @var string Request ID
|
||||
*/
|
||||
protected $requestId;
|
||||
|
||||
/**
|
||||
* @var string Exception type (client / server)
|
||||
*/
|
||||
protected $exceptionType;
|
||||
|
||||
/**
|
||||
* @var string Exception code
|
||||
*/
|
||||
protected $exceptionCode;
|
||||
|
||||
/**
|
||||
* Set the exception code
|
||||
*
|
||||
* @param string $code Exception code
|
||||
*/
|
||||
public function setExceptionCode($code) {
|
||||
$this->exceptionCode = $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the exception code
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getExceptionCode() {
|
||||
return $this->exceptionCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the exception type
|
||||
*
|
||||
* @param string $type Exception type
|
||||
*/
|
||||
public function setExceptionType($type) {
|
||||
$this->exceptionType = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the exception type (one of client or server)
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getExceptionType() {
|
||||
return $this->exceptionType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the request ID
|
||||
*
|
||||
* @param string $id Request ID
|
||||
*/
|
||||
public function setRequestId($id) {
|
||||
$this->requestId = $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Request ID
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getRequestId() {
|
||||
return $this->requestId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the associated response
|
||||
*
|
||||
* @param Response $response Response
|
||||
*/
|
||||
public function setResponse(Response $response) {
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the associated response object
|
||||
*
|
||||
* @return Response|null
|
||||
*/
|
||||
public function getResponse() {
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the associated request
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
*/
|
||||
public function setRequest(RequestInterface $request) {
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the associated request object
|
||||
*
|
||||
* @return RequestInterface|null
|
||||
*/
|
||||
public function getRequest() {
|
||||
return $this->request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the status code of the response
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getStatusCode() {
|
||||
return $this->response ? $this->response->getStatusCode() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast to a string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString() {
|
||||
$message = get_class($this) . ': '
|
||||
. 'Cos Error Code: ' . $this->getExceptionCode() . ', '
|
||||
. 'Status Code: ' . $this->getStatusCode() . ', '
|
||||
. 'Cos Request ID: ' . $this->getRequestId() . ', '
|
||||
. 'Cos Error Type: ' . $this->getExceptionType() . ', '
|
||||
. 'Cos Error Message: ' . $this->getMessage();
|
||||
|
||||
// Add the User-Agent if available
|
||||
if ($this->request) {
|
||||
$message .= ', ' . 'User-Agent: ' . $this->request->getHeader('User-Agent');
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the request ID of the error. This value is only present if a
|
||||
* response was received, and is not present in the event of a networking
|
||||
* error.
|
||||
*
|
||||
* Same as `getRequestId()` method, but matches the interface for SDKv3.
|
||||
*
|
||||
* @return string|null Returns null if no response was received
|
||||
*/
|
||||
public function getCosRequestId() {
|
||||
return $this->requestId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Cos error type.
|
||||
*
|
||||
* Same as `getExceptionType()` method, but matches the interface for SDKv3.
|
||||
*
|
||||
* @return string|null Returns null if no response was received
|
||||
*/
|
||||
public function getCosErrorType() {
|
||||
return $this->exceptionType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Cos error code.
|
||||
*
|
||||
* Same as `getExceptionCode()` method, but matches the interface for SDKv3.
|
||||
*
|
||||
* @return string|null Returns null if no response was received
|
||||
*/
|
||||
public function getCosErrorCode() {
|
||||
return $this->exceptionCode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Qcloud\Cos;
|
||||
|
||||
use Qcloud\Cos\Exception\ServiceResponseException;
|
||||
use Qcloud\Cos\Exception\NoSuchKeyException;
|
||||
|
||||
use Guzzle\Common\Event;
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
use Guzzle\Http\Message\Response;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Converts generic Guzzle response exceptions into cos specific exceptions
|
||||
*/
|
||||
class ExceptionListener implements EventSubscriberInterface {
|
||||
protected $parser;
|
||||
protected $defaultException;
|
||||
|
||||
public function __construct() {
|
||||
$this->parser = new ExceptionParser();
|
||||
$this->defaultException = 'Qcloud\Cos\Exception\ServiceResponseException';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
return array('request.error' => array('onRequestError', -1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws a more meaningful request exception if available
|
||||
*
|
||||
* @param Event $event Event emitted
|
||||
*/
|
||||
public function onRequestError(Event $event) {
|
||||
$e = $this->fromResponse($event['request'], $event['response']);
|
||||
$event->stopPropagation();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
public function fromResponse(RequestInterface $request, Response $response) {
|
||||
$parts = $this->parser->parse($request, $response);
|
||||
|
||||
$className = 'Qcloud\\Cos\\Exception\\' . $parts['code'];
|
||||
if (substr($className, -9) !== 'Exception') {
|
||||
$className .= 'Exception';
|
||||
}
|
||||
|
||||
$className = class_exists($className) ? $className : $this->defaultException;
|
||||
|
||||
return $this->createException($className, $request, $response, $parts);
|
||||
}
|
||||
|
||||
protected function createException($className, RequestInterface $request, Response $response, array $parts) {
|
||||
$class = new $className($parts['message']);
|
||||
|
||||
if ($class instanceof ServiceResponseException) {
|
||||
$class->setExceptionCode($parts['code']);
|
||||
$class->setExceptionType($parts['type']);
|
||||
$class->setResponse($response);
|
||||
$class->setRequest($request);
|
||||
$class->setRequestId($parts['request_id']);
|
||||
}
|
||||
|
||||
return $class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
namespace Qcloud\Cos;
|
||||
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
use Guzzle\Http\Message\Response;
|
||||
|
||||
/**
|
||||
* Parses default XML exception responses
|
||||
*/
|
||||
class ExceptionParser {
|
||||
|
||||
public function parse(RequestInterface $request, Response $response) {
|
||||
$data = array(
|
||||
'code' => null,
|
||||
'message' => null,
|
||||
'type' => $response->isClientError() ? 'client' : 'server',
|
||||
'request_id' => null,
|
||||
'parsed' => null
|
||||
);
|
||||
|
||||
$body = $response->getBody(true);
|
||||
|
||||
if (!$body) {
|
||||
$this->parseHeaders($request, $response, $data);
|
||||
return $data;
|
||||
}
|
||||
|
||||
try {
|
||||
$xml = new \SimpleXMLElement($body);
|
||||
$this->parseBody($xml, $data);
|
||||
return $data;
|
||||
} catch (\Exception $e) {
|
||||
// Gracefully handle parse errors. This could happen when the
|
||||
// server responds with a non-XML response (e.g., private beta
|
||||
// services).
|
||||
$data['code'] = 'PhpInternalXmlParseError';
|
||||
$data['message'] = 'A non-XML response was received';
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses additional exception information from the response headers
|
||||
*
|
||||
* @param RequestInterface $request Request that was issued
|
||||
* @param Response $response The response from the request
|
||||
* @param array $data The current set of exception data
|
||||
*/
|
||||
protected function parseHeaders(RequestInterface $request, Response $response, array &$data) {
|
||||
$data['message'] = $response->getStatusCode() . ' ' . $response->getReasonPhrase();
|
||||
if ($requestId = $response->getHeader('x-cos-request-id')) {
|
||||
$data['request_id'] = $requestId;
|
||||
$data['message'] .= " (Request-ID: $requestId)";
|
||||
}
|
||||
|
||||
// Get the request
|
||||
$status = $response->getStatusCode();
|
||||
$method = $request->getMethod();
|
||||
|
||||
// Attempt to determine code for 403s and 404s
|
||||
if ($status === 403) {
|
||||
$data['code'] = 'AccessDenied';
|
||||
} elseif ($method === 'HEAD' && $status === 404) {
|
||||
$path = explode('/', trim($request->getPath(), '/'));
|
||||
$host = explode('.', $request->getHost());
|
||||
$bucket = (count($host) >= 4) ? $host[0] : array_shift($path);
|
||||
$object = array_shift($path);
|
||||
|
||||
if ($bucket && $object) {
|
||||
$data['code'] = 'NoSuchKey';
|
||||
} elseif ($bucket) {
|
||||
$data['code'] = 'NoSuchBucket';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses additional exception information from the response body
|
||||
*
|
||||
* @param \SimpleXMLElement $body The response body as XML
|
||||
* @param array $data The current set of exception data
|
||||
*/
|
||||
protected function parseBody(\SimpleXMLElement $body, array &$data) {
|
||||
$data['parsed'] = $body;
|
||||
|
||||
$namespaces = $body->getDocNamespaces();
|
||||
if (isset($namespaces[''])) {
|
||||
// Account for the default namespace being defined and PHP not being able to handle it :(
|
||||
$body->registerXPathNamespace('ns', $namespaces['']);
|
||||
$prefix = 'ns:';
|
||||
} else {
|
||||
$prefix = '';
|
||||
}
|
||||
|
||||
if ($tempXml = $body->xpath("//{$prefix}Code[1]")) {
|
||||
$data['code'] = (string) $tempXml[0];
|
||||
}
|
||||
|
||||
if ($tempXml = $body->xpath("//{$prefix}Message[1]")) {
|
||||
$data['message'] = (string) $tempXml[0];
|
||||
}
|
||||
|
||||
$tempXml = $body->xpath("//{$prefix}RequestId[1]");
|
||||
if (empty($tempXml)) {
|
||||
$tempXml = $body->xpath("//{$prefix}RequestID[1]");
|
||||
}
|
||||
if (isset($tempXml[0])) {
|
||||
$data['request_id'] = (string) $tempXml[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Qcloud\Cos;
|
||||
|
||||
use Guzzle\Common\Event;
|
||||
use Guzzle\Service\Command\CommandInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Adds required and optional Content-MD5 headers
|
||||
*/
|
||||
class Md5Listener implements EventSubscriberInterface
|
||||
{
|
||||
/** @var S3SignatureInterface */
|
||||
private $signature;
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array('command.after_prepare' => 'onCommandAfterPrepare');
|
||||
}
|
||||
|
||||
public function __construct(Signature $signature)
|
||||
{
|
||||
$this->signature = $signature;
|
||||
}
|
||||
|
||||
public function onCommandAfterPrepare(Event $event)
|
||||
{
|
||||
$command = $event['command'];
|
||||
$operation = $command->getOperation();
|
||||
|
||||
if ($operation->getData('contentMd5')) {
|
||||
// Add the MD5 if it is required for all signers
|
||||
$this->addMd5($command);
|
||||
} elseif ($operation->hasParam('ContentMD5')) {
|
||||
$value = $command['ContentMD5'];
|
||||
// Add a computed MD5 if the parameter is set to true or if
|
||||
// not using Signature V4 and the value is not set (null).
|
||||
if ($value === true ||
|
||||
($value === null && !($this->signature instanceof SignatureV4))
|
||||
) {
|
||||
$this->addMd5($command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function addMd5(CommandInterface $command)
|
||||
{
|
||||
$request = $command->getRequest();
|
||||
$body = $request->getBody();
|
||||
if ($body && $body->getSize() > 0) {
|
||||
if (false !== ($md5 = $body->getContentMd5(true, true))) {
|
||||
$request->setHeader('Content-MD5', $md5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace Qcloud\Cos;
|
||||
|
||||
use Guzzle\Http\ReadLimitEntityBody;
|
||||
use Qcloud\Cos\Exception\CosException;
|
||||
class MultipartUpload {
|
||||
/**
|
||||
* const var: part size from 5MB to 5GB, and max parts of 10000 are allowed for each upload.
|
||||
*/
|
||||
const MIN_PART_SIZE = 5242880;
|
||||
const MAX_PART_SIZE = 5368709120;
|
||||
const MAX_PARTS = 10000;
|
||||
|
||||
private $client;
|
||||
private $source;
|
||||
private $options;
|
||||
private $partSize;
|
||||
|
||||
public function __construct($client, $source, $minPartSize, $options = array()) {
|
||||
$this->client = $client;
|
||||
$this->source = $source;
|
||||
$this->options = $options;
|
||||
$this->partSize = $this->calculatePartSize($minPartSize);
|
||||
}
|
||||
|
||||
public function performUploading() {
|
||||
$uploadId = $this->initiateMultipartUpload();
|
||||
|
||||
$partNumber = 1;
|
||||
$parts = array();
|
||||
for (;;) {
|
||||
if ($this->source->isConsumed()) {
|
||||
break;
|
||||
}
|
||||
|
||||
$body = new ReadLimitEntityBody($this->source, $this->partSize, $this->source->ftell());
|
||||
if ($body->getContentLength() == 0) {
|
||||
break;
|
||||
}
|
||||
$result = $this->client->uploadPart(array(
|
||||
'Bucket' => $this->options['Bucket'],
|
||||
'Key' => $this->options['Key'],
|
||||
'Body' => $body,
|
||||
'UploadId' => $uploadId,
|
||||
'PartNumber' => $partNumber));
|
||||
if (md5($body) != substr($result['ETag'], 1, -1)){
|
||||
throw new CosException("ETag check inconsistency");
|
||||
}
|
||||
$part = array('PartNumber' => $partNumber, 'ETag' => $result['ETag']);
|
||||
array_push($parts, $part);
|
||||
++$partNumber;
|
||||
}
|
||||
try {
|
||||
$rt = $this->client->completeMultipartUpload(array(
|
||||
'Bucket' => $this->options['Bucket'],
|
||||
'Key' => $this->options['Key'],
|
||||
'UploadId' => $uploadId,
|
||||
'Parts' => $parts));
|
||||
} catch(\Exception $e){
|
||||
throw $e;
|
||||
}
|
||||
return $rt;
|
||||
}
|
||||
|
||||
public function resumeUploading() {
|
||||
$uploadId = $this->options['UploadId'];
|
||||
$rt = $this->client->ListParts(
|
||||
array('UploadId' => $uploadId,
|
||||
'Bucket'=>$this->options['Bucket'],
|
||||
'Key'=>$this->options['Key']));
|
||||
$parts = array();
|
||||
$offset = $this->partSize;
|
||||
if (count($rt['Parts']) > 0) {
|
||||
foreach ($rt['Parts'] as $part) {
|
||||
$parts[$part['PartNumber'] - 1] = array('PartNumber' => $part['PartNumber'], 'ETag' => $part['ETag']);
|
||||
}
|
||||
}
|
||||
for ($partNumber = 1;;++$partNumber,$offset+=$body->getContentLength()) {
|
||||
if ($this->source->isConsumed()) {
|
||||
break;
|
||||
}
|
||||
|
||||
$body = new ReadLimitEntityBody($this->source, $this->partSize, $this->source->ftell());
|
||||
if ($body->getContentLength() == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (array_key_exists($partNumber-1,$parts)){
|
||||
|
||||
if (md5($body) != substr($parts[$partNumber-1]['ETag'], 1, -1)){
|
||||
throw new CosException("ETag check inconsistency");
|
||||
}
|
||||
$body->setOffset($offset);
|
||||
continue;
|
||||
}
|
||||
|
||||
$result = $this->client->uploadPart(array(
|
||||
'Bucket' => $this->options['Bucket'],
|
||||
'Key' => $this->options['Key'],
|
||||
'Body' => $body,
|
||||
'UploadId' => $uploadId,
|
||||
'PartNumber' => $partNumber));
|
||||
if (md5($body) != substr($result['ETag'], 1, -1)){
|
||||
throw new CosException("ETag check inconsistency");
|
||||
}
|
||||
$parts[$partNumber-1] = array('PartNumber' => $partNumber, 'ETag' => $result['ETag']);
|
||||
|
||||
}
|
||||
$rt = $this->client->completeMultipartUpload(array(
|
||||
'Bucket' => $this->options['Bucket'],
|
||||
'Key' => $this->options['Key'],
|
||||
'UploadId' => $uploadId,
|
||||
'Parts' => $parts));
|
||||
return $rt;
|
||||
}
|
||||
|
||||
private function calculatePartSize($minPartSize) {
|
||||
$partSize = intval(ceil(($this->source->getContentLength() / 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'];
|
||||
}
|
||||
}
|
||||
4328
app/Common/extend/tencentcloud/src/Qcloud/Cos/Service.php
Normal file
4328
app/Common/extend/tencentcloud/src/Qcloud/Cos/Service.php
Normal file
File diff suppressed because it is too large
Load Diff
50
app/Common/extend/tencentcloud/src/Qcloud/Cos/Signature.php
Normal file
50
app/Common/extend/tencentcloud/src/Qcloud/Cos/Signature.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
namespace Qcloud\Cos;
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
class Signature {
|
||||
private $accessKey; // string: access key.
|
||||
private $secretKey; // string: secret key.
|
||||
public function __construct($accessKey, $secretKey) {
|
||||
$this->accessKey = $accessKey;
|
||||
$this->secretKey = $secretKey;
|
||||
}
|
||||
public function __destruct() {
|
||||
}
|
||||
public function signRequest(RequestInterface $request) {
|
||||
$signTime = (string)(time() - 60) . ';' . (string)(time() + 3600);
|
||||
$httpString = strtolower($request->getMethod()) . "\n" . urldecode($request->getPath()) .
|
||||
"\n\nhost=" . $request->getHost() . "\n";
|
||||
$sha1edHttpString = sha1($httpString);
|
||||
$stringToSign = "sha1\n$signTime\n$sha1edHttpString\n";
|
||||
$signKey = hash_hmac('sha1', $signTime, $this->secretKey);
|
||||
$signature = hash_hmac('sha1', $stringToSign, $signKey);
|
||||
$authorization = 'q-sign-algorithm=sha1&q-ak='. $this->accessKey .
|
||||
"&q-sign-time=$signTime&q-key-time=$signTime&q-header-list=host&q-url-param-list=&" .
|
||||
"q-signature=$signature";
|
||||
$request->setHeader('Authorization', $authorization);
|
||||
}
|
||||
public function createAuthorization(
|
||||
RequestInterface $request,
|
||||
$expires = "10 minutes"
|
||||
) {
|
||||
$signTime = (string)(time() - 60) . ';' . (string)(strtotime($expires));
|
||||
$httpString = strtolower($request->getMethod()) . "\n" . urldecode($request->getPath()) .
|
||||
"\n\nhost=" . $request->getHost() . "\n";
|
||||
$sha1edHttpString = sha1($httpString);
|
||||
$stringToSign = "sha1\n$signTime\n$sha1edHttpString\n";
|
||||
$signKey = hash_hmac('sha1', $signTime, $this->secretKey);
|
||||
$signature = hash_hmac('sha1', $stringToSign, $signKey);
|
||||
$authorization = 'q-sign-algorithm=sha1&q-ak='. $this->accessKey .
|
||||
"&q-sign-time=$signTime&q-key-time=$signTime&q-header-list=host&q-url-param-list=&" .
|
||||
"q-signature=$signature";
|
||||
return $authorization;
|
||||
}
|
||||
public function createPresignedUrl(
|
||||
RequestInterface $request,
|
||||
$expires = "10 minutes"
|
||||
) {
|
||||
$authorization = $this->createAuthorization($request, $expires);
|
||||
$request->getQuery()->add('sign', $authorization);
|
||||
return $request->getUrl();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Qcloud\Cos;
|
||||
|
||||
use Guzzle\Common\Event;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Listener used to sign requests before they are sent over the wire.
|
||||
*/
|
||||
class SignatureListener implements EventSubscriberInterface {
|
||||
// cos signature.
|
||||
protected $signature;
|
||||
|
||||
/**
|
||||
* Construct a new request signing plugin
|
||||
*/
|
||||
public function __construct($accessKey, $secretKey) {
|
||||
$this->signature = new Signature($accessKey, $secretKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
'request.before_send' => array('onRequestBeforeSend', -255));
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs requests before they are sent
|
||||
*
|
||||
* @param Event $event Event emitted
|
||||
*/
|
||||
public function onRequestBeforeSend(Event $event) {
|
||||
|
||||
$this->signature->signRequest($event['request']);
|
||||
/*
|
||||
if(!$this->credentials instanceof NullCredentials) {
|
||||
$this->signature->signRequest($event['request'], $this->credentials);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
1367
app/Common/extend/tencentcloud/src/Qcloud/Cos/Tests/Test.php
Normal file
1367
app/Common/extend/tencentcloud/src/Qcloud/Cos/Tests/Test.php
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Qcloud\Cos\Tests;
|
||||
|
||||
use Qcloud\Cos\Client;
|
||||
|
||||
class TestHelper {
|
||||
|
||||
public static function nuke($bucket) {
|
||||
try {
|
||||
$cosClient = new Client(array('region' => getenv('COS_REGION'),
|
||||
'credentials'=> array(
|
||||
'appId' => getenv('COS_APPID'),
|
||||
'secretId' => getenv('COS_KEY'),
|
||||
'secretKey' => getenv('COS_SECRET'))));
|
||||
$result = $cosClient->listObjects(array('Bucket' => $bucket));
|
||||
if ($result->get('Contents')) {
|
||||
foreach ($result ->get('Contents') as $content) {
|
||||
$cosClient->deleteObject(array('Bucket' => $bucket, 'Key' => $content['Key']));
|
||||
}
|
||||
}
|
||||
$cosClient->deleteBucket(array('Bucket' => $bucket));
|
||||
|
||||
while(True){
|
||||
$result = $cosClient->ListMultipartUploads(
|
||||
array('Bucket' => $bucket,
|
||||
'Prefix' => ''));
|
||||
if (count($result['Uploads']) == 0){
|
||||
break;
|
||||
}
|
||||
foreach ($result['Uploads'] as $upload) {
|
||||
try {
|
||||
$rt = $cosClient->AbortMultipartUpload(
|
||||
array('Bucket' => $bucket,
|
||||
'Key' => $upload['Key'],
|
||||
'UploadId' => $upload['UploadId']));
|
||||
print_r($rt);
|
||||
} catch (\Exception $e) {
|
||||
print_r($e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
//echo "$e\n";
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Qcloud\Cos;
|
||||
|
||||
use Aws\Common\Credentials\CredentialsInterface;
|
||||
use Aws\Common\Credentials\NullCredentials;
|
||||
use Guzzle\Common\Event;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Listener used to sign requests before they are sent over the wire.
|
||||
*/
|
||||
class TokenListener implements EventSubscriberInterface {
|
||||
// cos signature.
|
||||
protected $token;
|
||||
|
||||
/**
|
||||
* Construct a new request signing plugin
|
||||
*/
|
||||
public function __construct($token) {
|
||||
$this->token = $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
'request.before_send' => array('onRequestBeforeSend', -240));
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs requests before they are sent
|
||||
*
|
||||
* @param Event $event Event emitted
|
||||
*/
|
||||
public function onRequestBeforeSend(Event $event) {
|
||||
if ($this->token != null) {
|
||||
$event['request']->setHeader('x-cos-security-token', $this->token);
|
||||
}
|
||||
/*
|
||||
if(!$this->credentials instanceof NullCredentials) {
|
||||
$this->signature->signRequest($event['request'], $this->credentials);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace Qcloud\Cos;
|
||||
|
||||
use Qcloud\Cos\Exception\InvalidArgumentException;
|
||||
use Guzzle\Common\Event;
|
||||
use Guzzle\Http\EntityBody;
|
||||
use Guzzle\Service\Command\AbstractCommand as Command;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
* Prepares the body parameter of a command such that the parameter is more flexible
|
||||
* (e.g. accepts file handles) with the value it accepts but converts it to the correct format
|
||||
* for the command. Also looks for a "Filename" parameter.
|
||||
*/
|
||||
class UploadBodyListener implements EventSubscriberInterface {
|
||||
/**
|
||||
* @var array The names of the commands of which to modify the body parameter
|
||||
*/
|
||||
protected $commands;
|
||||
|
||||
/**
|
||||
* @var string The key for the upload body parameter
|
||||
*/
|
||||
protected $bodyParameter;
|
||||
|
||||
/**
|
||||
* @var string The key for the source file parameter
|
||||
*/
|
||||
protected $sourceParameter;
|
||||
|
||||
/**
|
||||
* @param array $commands The commands to modify
|
||||
* @param string $bodyParameter The key for the body parameter
|
||||
* @param string $sourceParameter The key for the source file parameter
|
||||
*/
|
||||
public function __construct(array $commands, $bodyParameter = 'Body', $sourceParameter = 'SourceFile') {
|
||||
$this->commands = $commands;
|
||||
$this->bodyParameter = (string) $bodyParameter;
|
||||
$this->sourceParameter = (string) $sourceParameter;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
return array('command.before_prepare' => array('onCommandBeforePrepare'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts filenames and file handles into EntityBody objects before the command is validated
|
||||
*
|
||||
* @param Event $event Event emitted
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function onCommandBeforePrepare(Event $event) {
|
||||
/** @var Command $command */
|
||||
$command = $event['command'];
|
||||
if (in_array($command->getName(), $this->commands)) {
|
||||
// Get the interesting parameters
|
||||
$source = $command->get($this->sourceParameter);
|
||||
$body = $command->get($this->bodyParameter);
|
||||
|
||||
// If a file path is passed in then get the file handle
|
||||
if (is_string($source) && file_exists($source)) {
|
||||
$body = fopen($source, 'rb');
|
||||
}
|
||||
|
||||
// Prepare the body parameter and remove the source file parameter
|
||||
if (null !== $body) {
|
||||
$command->remove($this->sourceParameter);
|
||||
$command->set($this->bodyParameter, EntityBody::factory($body));
|
||||
} else {
|
||||
throw new InvalidArgumentException(
|
||||
"You must specify a non-null value for the {$this->bodyParameter} or {$this->sourceParameter} parameters.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user