提交vendor文件夹

This commit is contained in:
2026-03-11 18:19:40 +08:00
commit 4b490670f1
4332 changed files with 631008 additions and 0 deletions

606
vendor/qcloud/cos-sdk-v5/src/Client.php vendored Normal file
View File

@ -0,0 +1,606 @@
<?php
namespace Qcloud\Cos;
use GuzzleHttp\Client as HttpClient;
use GuzzleHttp\HandlerStack;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\Command\Guzzle\Description;
use GuzzleHttp\Command\Guzzle\GuzzleClient;
use GuzzleHttp\Command\Guzzle\Deserializer;
use GuzzleHttp\Command\CommandInterface;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Middleware;
use GuzzleHttp\Psr7;
/**
* @method object AbortMultipartUpload(array $args) 舍弃一个分块上传且删除已上传的分片块
* @method object CreateBucket(array $args) 创建存储桶Bucket
* @method object CompleteMultipartUpload(array $args) 完成整个分块上传
* @method object CreateMultipartUpload(array $args) 初始化分块上传
* @method object CopyObject(array $args) 复制对象
* @method object DeleteBucket(array $args) 删除存储桶 (Bucket)
* @method object DeleteBucketCors(array $args) 删除跨域访问配置信息
* @method object DeleteBucketTagging(array $args) 删除存储桶标签信息
* @method object DeleteBucketInventory(array $args) 删除存储桶标清单任务
* @method object DeleteObject(array $args) 删除 COS 上单个对象
* @method object DeleteObjects(array $args) 批量删除 COS 对象
* @method object DeleteBucketWebsite(array $args) 删除存储桶Bucket的website
* @method object DeleteBucketLifecycle(array $args) 删除存储桶Bucket的生命周期配置
* @method object DeleteBucketReplication(array $args) 删除跨区域复制配置
* @method object PutObjectTagging(array $args) 配置对象标签
* @method object GetObjectTagging(array $args) 获取对象标签信息
* @method object DeleteObjectTagging(array $args) 删除对象标签
* @method object GetObject(array $args) 下载对象
* @method object GetObjectAcl(array $args) 获取 COS 对象的访问权限信息Access Control List, ACL
* @method object GetBucketAcl(array $args) 获取存储桶Bucket的访问权限信息Access Control List, ACL
* @method object GetBucketCors(array $args) 查询存储桶Bucket跨域访问配置信息
* @method object GetBucketDomain(array $args) 查询存储桶BucketDomain配置信息
* @method object GetBucketAccelerate(array $args) 查询存储桶BucketAccelerate配置信息
* @method object GetBucketWebsite(array $args) 查询存储桶BucketWebsite配置信息
* @method object GetBucketLifecycle(array $args) 查询存储桶Bucket的生命周期配置
* @method object GetBucketVersioning(array $args) 获取存储桶Bucket版本控制信息
* @method object GetBucketReplication(array $args) 获取存储桶Bucket跨区域复制配置信息
* @method object GetBucketLocation(array $args) 获取存储桶Bucket所在的地域信息
* @method object GetBucketNotification(array $args) 获取存储桶BucketNotification信息
* @method object GetBucketLogging(array $args) 获取存储桶Bucket日志信息
* @method object GetBucketInventory(array $args) 获取存储桶Bucket清单信息
* @method object GetBucketTagging(array $args) 获取存储桶Bucket标签信息
* @method object UploadPart(array $args) 分块上传
* @method object PutObject(array $args) 上传对象
* @method object AppendObject(array $args) 追加对象
* @method object PutObjectAcl(array $args) 设置 COS 对象的访问权限信息Access Control List, ACL
* @method object PutBucketAcl(array $args) 设置存储桶Bucket的访问权限Access Control List, ACL)
* @method object PutBucketCors(array $args) 设置存储桶Bucket的跨域配置信息
* @method object PutBucketDomain(array $args) 设置存储桶Bucket的Domain信息
* @method object PutBucketLifecycle(array $args) 设置存储桶Bucket生命周期配置
* @method object PutBucketVersioning(array $args) 存储桶Bucket版本控制
* @method object PutBucketAccelerate(array $args) 配置存储桶BucketAccelerate
* @method object PutBucketWebsite(array $args) 配置存储桶Bucketwebsite
* @method object PutBucketReplication(array $args) 配置存储桶Bucket跨区域复制
* @method object PutBucketNotification(array $args) 设置存储桶Bucket的回调设置
* @method object PutBucketTagging(array $args) 配置存储桶Bucket标签
* @method object PutBucketLogging(array $args) 开启存储桶Bucket日志服务
* @method object PutBucketInventory(array $args) 配置存储桶Bucket清单
* @method object RestoreObject(array $args) 回热归档对象
* @method object ListParts(array $args) 查询存储桶Bucket中正在进行中的分块上传对象
* @method object ListObjects(array $args) 查询存储桶Bucket下的部分或者全部对象
* @method object ListBuckets 获取所属账户的所有存储空间列表
* @method object ListObjectVersions(array $args) 获取多版本对象
* @method object ListMultipartUploads(array $args) 获取已上传分块列表
* @method object ListBucketInventoryConfigurations(array $args) 获取清单列表
* @method object HeadObject(array $args) 获取对象的meta信息
* @method object HeadBucket(array $args) 存储桶Bucket是否存在
* @method object UploadPartCopy(array $args) 分块copy
* @method object SelectObjectContent(array $args) 检索对象内容
* @method object PutBucketIntelligentTiering(array $args) 存储桶Bucket开启智能分层
* @method object GetBucketIntelligentTiering(array $args) 查询存储桶Bucket智能分层
* @method object ImageInfo(array $args) 万象-获取图片基本信息
* @method object ImageExif(array $args) 万象-获取图片EXIF信息
* @method object ImageAve(array $args) 万象-获取图片主色调信息
* @method object ImageProcess(array $args) 万象-云上数据处理
* @method object Qrcode(array $args) 万象-二维码下载时识别
* @method object QrcodeGenerate(array $args) 万象-二维码生成
* @method object DetectLabel(array $args) 万象-图片标签
* @method object PutBucketImageStyle(array $args) 万象-增加样式
* @method object GetBucketImageStyle(array $args) 万象-查询样式
* @method object DeleteBucketImageStyle(array $args) 万象-删除样式
* @method object PutBucketGuetzli(array $args) 万象-开通Guetzli压缩
* @method object GetBucketGuetzli(array $args) 万象-查询Guetzli状态
* @method object DeleteBucketGuetzli(array $args) 万象-关闭Guetzli压缩
* @method object GetObjectSensitiveContentRecognition(array $args) 图片审核
* @method object DetectText(array $args) 文本审核
* @method object GetSnapshot(array $args) 媒体截图
* @method object PutBucketReferer(array $args) 添加防盗链
* @method object GetBucketReferer(array $args) 获取防盗链规则
* @method object GetMediaInfo(array $args) 获取媒体信息
* @method object CreateMediaTranscodeJobs(array $args) 媒体转码
* @method object CreateMediaJobs(array $args) 媒体任务
* @method object DescribeMediaJob(array $args) 查询指定的媒体任务
* @method object DescribeMediaJobs(array $args) 拉取拉取符合条件的媒体任务
* @method object CreateMediaSnapshotJobs(array $args) 媒体截图
* @method object CreateMediaConcatJobs(array $args) 媒体拼接
* @method object DetectAudio(array $args) 音频审核
* @method object GetDetectAudioResult(array $args) 主动获取音频审核结果
* @method object GetDetectTextResult(array $args) 主动获取文本文件审核结果
* @method object DetectVideo(array $args) 视频审核
* @method object GetDetectVideoResult(array $args) 主动获取视频审核结果
* @method object DetectDocument(array $args) 文档审核
* @method object GetDetectDocumentResult(array $args) 主动获取文档审核结果
* @method object CreateDocProcessJobs(array $args) 提交文档转码任务
* @method object DescribeDocProcessQueues(array $args) 查询文档转码队列
* @method object DescribeDocProcessJob(array $args) 查询文档转码任务
* @method object GetDescribeDocProcessJobs(array $args) 拉取符合条件的文档转码任务
* @method object DetectImage(array $args) 图片审核
* @method object DetectImages(array $args) 图片审核-批量
* @method object DetectVirus(array $args) 云查毒
* @method object GetDetectVirusResult(array $args) 查询病毒检测任务结果
* @method object GetDetectImageResult(array $args) 主动获取图片审核结果
* @method object CreateMediaVoiceSeparateJobs(array $args) 提交人声分离任务
* @method object DescribeMediaVoiceSeparateJob(array $args) 查询指定的人声分离任务
* @method object DetectWebpage(array $args) 提交网页审核任务
* @method object GetDetectWebpageResult(array $args) 查询网页审核任务结果
* @method object DescribeMediaBuckets(array $args) 查询媒体处理开通状态
* @method object GetPrivateM3U8(array $args) 获取私有 M3U8 ts 资源的下载授权
* @method object DescribeMediaQueues(array $args) 搜索媒体处理队列
* @method object UpdateMediaQueue(array $args) 更新媒体处理队列
* @method object CreateMediaSmartCoverJobs(array $args) 提交智能封面任务
* @method object CreateMediaVideoProcessJobs(array $args) 提交视频增强任务
* @method object CreateMediaVideoMontageJobs(array $args) 提交精彩集锦任务
* @method object CreateMediaAnimationJobs(array $args) 提交动图任务
* @method object CreateMediaPicProcessJobs(array $args) 提交图片处理任务
* @method object CreateMediaSegmentJobs(array $args) 提交转封装任务
* @method object CreateMediaVideoTagJobs(array $args) 提交视频标签任务
* @method object CreateMediaSuperResolutionJobs(array $args) 提交超分辨率任务
* @method object CreateMediaSDRtoHDRJobs(array $args) 提交 SDR to HDR 任务
* @method object CreateMediaDigitalWatermarkJobs(array $args) 嵌入数字水印任务(添加水印)
* @method object CreateMediaExtractDigitalWatermarkJobs(array $args) 提取数字水印任务(提取水印)
* @method object DetectLiveVideo(array $args) 直播流审核
* @method object CancelLiveVideoAuditing(array $args) 取消直播流审核
* @method object OpticalOcrRecognition(array $args) 通用文字识别
* @method object TriggerWorkflow(array $args) 手动触发工作流
* @method object GetWorkflowInstances(array $args) 获取工作流实例列表
* @method object GetWorkflowInstance(array $args) 获取工作流实例详情
* @method object CreateMediaSnapshotTemplate(array $args) 新增截图模板
* @method object UpdateMediaSnapshotTemplate(array $args) 更新截图模板
* @method object CreateMediaTranscodeTemplate(array $args) 新增转码模板
* @method object UpdateMediaTranscodeTemplate(array $args) 更新转码模板
* @method object CreateMediaHighSpeedHdTemplate(array $args) 新增极速高清转码模板
* @method object UpdateMediaHighSpeedHdTemplate(array $args) 更新极速高清转码模板
* @method object CreateMediaAnimationTemplate(array $args) 新增动图模板
* @method object UpdateMediaAnimationTemplate(array $args) 更新动图模板
* @method object CreateMediaConcatTemplate(array $args) 新增拼接模板
* @method object UpdateMediaConcatTemplate(array $args) 更新拼接模板
* @method object CreateMediaVideoProcessTemplate(array $args) 新增视频增强模板
* @method object UpdateMediaVideoProcessTemplate(array $args) 更新视频增强模板
* @method object CreateMediaVideoMontageTemplate(array $args) 新增精彩集锦模板
* @method object UpdateMediaVideoMontageTemplate(array $args) 更新精彩集锦模板
* @method object CreateMediaVoiceSeparateTemplate(array $args) 新增人声分离模板
* @method object UpdateMediaVoiceSeparateTemplate(array $args) 更新人声分离模板
* @method object CreateMediaSuperResolutionTemplate(array $args) 新增超分辨率模板
* @method object UpdateMediaSuperResolutionTemplate(array $args) 更新超分辨率模板
* @method object CreateMediaPicProcessTemplate(array $args) 新增图片处理模板
* @method object UpdateMediaPicProcessTemplate(array $args) 更新图片处理模板
* @method object CreateMediaWatermarkTemplate(array $args) 新增水印模板
* @method object UpdateMediaWatermarkTemplate(array $args) 更新水印模板
* @method object DescribeMediaTemplates(array $args) 查询模板列表
* @method object DescribeWorkflow(array $args) 搜索工作流
* @method object DeleteWorkflow(array $args) 删除工作流
* @method object CreateInventoryTriggerJob(array $args) 触发批量存量任务
* @method object DescribeInventoryTriggerJobs(array $args) 批量拉取存量任务
* @method object DescribeInventoryTriggerJob(array $args) 查询存量任务
* @method object CancelInventoryTriggerJob(array $args) 取消存量任务
* @method object CreateMediaNoiseReductionJobs(array $args) 提交音频降噪任务
* @method object ImageRepairProcess(array $args) 图片水印修复
* @method object ImageDetectCarProcess(array $args) 车辆车牌检测
* @method object ImageAssessQualityProcess(array $args) 图片质量评估
* @method object ImageSearchOpen(array $args) 开通以图搜图
* @method object ImageSearchAdd(array $args) 添加图库图片
* @method object ImageSearch(array $args) 图片搜索接口
* @method object ImageSearchDelete(array $args) 图片搜索接口
* @method object BindCiService(array $args) 绑定数据万象服务
* @method object GetCiService(array $args) 查询数据万象服务
* @method object UnBindCiService(array $args) 解绑数据万象服务
* @method object GetHotLink(array $args) 查询防盗链
* @method object AddHotLink(array $args) 查询防盗链
* @method object OpenOriginProtect(array $args) 开通原图保护
* @method object GetOriginProtect(array $args) 查询原图保护状态
* @method object CloseOriginProtect(array $args) 关闭原图保护
* @method object ImageDetectFace(array $args) 人脸检测
* @method object ImageFaceEffect(array $args) 人脸特效
* @method object IDCardOCR(array $args) 身份证识别
* @method object IDCardOCRByUpload(array $args) 身份证识别-上传时处理
* @method object GetLiveCode(array $args) 获取数字验证码
* @method object GetActionSequence(array $args) 获取动作顺序
* @method object DescribeDocProcessBuckets(array $args) 查询文档预览开通状态
* @method object UpdateDocProcessQueue(array $args) 更新文档转码队列
* @method object CreateMediaQualityEstimateJobs(array $args) 提交视频质量评分任务
* @method object CreateMediaStreamExtractJobs(array $args) 提交音视频流分离任务
* @method object FileJobs4Hash(array $args) 哈希值计算同步请求
* @method object OpenFileProcessService(array $args) 开通文件处理服务
* @method object GetFileProcessQueueList(array $args) 搜索文件处理队列
* @method object UpdateFileProcessQueue(array $args) 更新文件处理的队列
* @method object CreateFileHashCodeJobs(array $args) 提交哈希值计算任务
* @method object GetFileHashCodeResult(array $args) 查询哈希值计算结果
* @method object CreateFileUncompressJobs(array $args) 提交文件解压任务
* @method object GetFileUncompressResult(array $args) 查询文件解压结果
* @method object CreateFileCompressJobs(array $args) 提交多文件打包压缩任务
* @method object GetFileCompressResult(array $args) 查询多文件打包压缩结果
* @method object CreateM3U8PlayListJobs(array $args) 获取指定hls/m3u8文件指定时间区间内的ts资源
* @method object GetPicQueueList(array $args) 搜索图片处理队列
* @method object UpdatePicQueue(array $args) 更新图片处理队列
* @method object GetPicBucketList(array $args) 查询图片处理服务状态
* @method object GetAiBucketList(array $args) 查询 AI 内容识别服务状态
* @method object OpenAiService(array $args) 开通 AI 内容识别
* @method object GetAiQueueList(array $args) 搜索 AI 内容识别队列
* @method object UpdateAiQueue(array $args) 更新 AI 内容识别队列
* @method object CreateMediaTranscodeProTemplate(array $args) 创建音视频转码 pro 模板
* @method object UpdateMediaTranscodeProTemplate(array $args) 更新音视频转码 pro 模板
* @method object CreateVoiceTtsTemplate(array $args) 创建语音合成模板
* @method object UpdateVoiceTtsTemplate(array $args) 更新语音合成模板
* @method object CreateMediaSmartCoverTemplate(array $args) 创建智能封面模板
* @method object UpdateMediaSmartCoverTemplate(array $args) 更新智能封面模板
* @method object CreateVoiceSpeechRecognitionTemplate(array $args) 创建语音识别模板
* @method object UpdateVoiceSpeechRecognitionTemplate(array $args) 更新语音识别模板
* @method object CreateVoiceTtsJobs(array $args) 提交一个语音合成任务
* @method object CreateAiTranslationJobs(array $args) 提交一个翻译任务
* @method object CreateVoiceSpeechRecognitionJobs(array $args) 提交一个语音识别任务
* @method object CreateAiWordsGeneralizeJobs(array $args) 提交一个分词任务
* @method object CreateMediaVideoEnhanceJobs(array $args) 提交画质增强任务
* @method object CreateMediaVideoEnhanceTemplate(array $args) 创建画质增强模板
* @method object UpdateMediaVideoEnhanceTemplate(array $args) 更新画质增强模板
* @method object OpenImageSlim(array $args) 开通图片瘦身
* @method object CloseImageSlim(array $args) 关闭图片瘦身
* @method object GetImageSlim(array $args) 查询图片瘦身状态
* @see \Qcloud\Cos\Service::getService()
*/
class Client extends GuzzleClient {
const VERSION = '2.6.5';
public $httpClient;
private $api;
private $desc;
private $action;
private $operation;
private $cosConfig;
private $signature;
private $rawCosConfig;
public function __construct(array $cosConfig) {
$this->rawCosConfig = $cosConfig;
$this->cosConfig['schema'] = isset($cosConfig['schema']) ? $cosConfig['schema'] : 'http';
$this->cosConfig['region'] = isset($cosConfig['region']) ? region_map($cosConfig['region']) : null;
$this->cosConfig['appId'] = isset($cosConfig['credentials']['appId']) ? $cosConfig['credentials']['appId'] : null;
$this->cosConfig['secretId'] = isset($cosConfig['credentials']['secretId']) ? trim($cosConfig['credentials']['secretId']) : '';
$this->cosConfig['secretKey'] = isset($cosConfig['credentials']['secretKey']) ? trim($cosConfig['credentials']['secretKey']) : '';
$this->cosConfig['anonymous'] = isset($cosConfig['credentials']['anonymous']) ? $cosConfig['credentials']['anonymous'] : false;
$this->cosConfig['token'] = isset($cosConfig['credentials']['token']) ? trim($cosConfig['credentials']['token']) : null;
$this->cosConfig['timeout'] = isset($cosConfig['timeout']) ? $cosConfig['timeout'] : 3600;
$this->cosConfig['connect_timeout'] = isset($cosConfig['connect_timeout']) ? $cosConfig['connect_timeout'] : 3600;
$this->cosConfig['ip'] = isset($cosConfig['ip']) ? $cosConfig['ip'] : null;
$this->cosConfig['port'] = isset($cosConfig['port']) ? $cosConfig['port'] : null;
$this->cosConfig['endpoint'] = isset($cosConfig['endpoint']) ? $cosConfig['endpoint'] : null;
$this->cosConfig['domain'] = isset($cosConfig['domain']) ? $cosConfig['domain'] : null;
$this->cosConfig['proxy'] = isset($cosConfig['proxy']) ? $cosConfig['proxy'] : null;
$this->cosConfig['retry'] = isset($cosConfig['retry']) ? $cosConfig['retry'] : 1;
$this->cosConfig['userAgent'] = isset($cosConfig['userAgent']) ? $cosConfig['userAgent'] : 'cos-php-sdk-v5.'. Client::VERSION;
$this->cosConfig['pathStyle'] = isset($cosConfig['pathStyle']) ? $cosConfig['pathStyle'] : false;
$this->cosConfig['signHost'] = isset($cosConfig['signHost']) ? $cosConfig['signHost'] : true;
$this->cosConfig['allow_redirects'] = isset($cosConfig['allow_redirects']) ? $cosConfig['allow_redirects'] : false;
$this->cosConfig['allow_accelerate'] = isset($cosConfig['allow_accelerate']) ? $cosConfig['allow_accelerate'] : false;
$this->cosConfig['timezone'] = isset($cosConfig['timezone']) ? $cosConfig['timezone'] : 'PRC';
$this->cosConfig['locationWithSchema'] = isset($cosConfig['locationWithSchema']) ? $cosConfig['locationWithSchema'] : false;
// check config
$this->inputCheck();
$service = Service::getService();
$handler = HandlerStack::create();
$handler->push(Middleware::retry($this->retryDecide(), $this->retryDelay()));
$handler->push(Middleware::mapRequest(function (RequestInterface $request) {
return $request->withHeader('User-Agent', $this->cosConfig['userAgent']);
}));
if ($this->cosConfig['anonymous'] != true) {
$handler->push($this::handleSignature($this->cosConfig['secretId'], $this->cosConfig['secretKey'], $this->cosConfig));
}
if ($this->cosConfig['token'] != null) {
$handler->push(Middleware::mapRequest(function (RequestInterface $request) {
$request = $request->withHeader('x-ci-security-token', $this->cosConfig['token']);
return $request->withHeader('x-cos-security-token', $this->cosConfig['token']);
}));
}
$handler->push($this::handleErrors());
$this->signature = new Signature($this->cosConfig['secretId'], $this->cosConfig['secretKey'], $this->cosConfig, $this->cosConfig['token']);
$area = $this->cosConfig['allow_accelerate'] ? 'accelerate' : $this->cosConfig['region'];
$this->httpClient = new HttpClient([
'base_uri' => "{$this->cosConfig['schema']}://cos.{$area}.myqcloud.com/",
'timeout' => $this->cosConfig['timeout'],
'handler' => $handler,
'proxy' => $this->cosConfig['proxy'],
'allow_redirects' => $this->cosConfig['allow_redirects']
]);
$this->desc = new Description($service);
$this->api = (array) $this->desc->getOperations();
parent::__construct($this->httpClient, $this->desc, [$this,
'commandToRequestTransformer'], [$this, 'responseToResultTransformer'],
null);
}
public function inputCheck() {
$message = null;
//检查Region
if (empty($this->cosConfig['region']) &&
empty($this->cosConfig['domain']) &&
empty($this->cosConfig['endpoint']) &&
empty($this->cosConfig['ip']) &&
!$this->cosConfig['allow_accelerate']) {
$message = 'Region is empty';
}
//检查Secret
if (empty($this->cosConfig['secretId']) || empty($this->cosConfig['secretKey'])) {
$message = 'Secret is empty';
}
if ($message !== null) {
$e = new Exception\CosException($message);
$e->setExceptionCode('Invalid Argument');
throw $e;
}
}
public function retryDecide() {
return function (
$retries,
RequestInterface $request,
ResponseInterface $response = null,
\Exception $exception = null
) {
if ($retries >= $this->cosConfig['retry']) {
return false;
}
if ($response != null && $response->getStatusCode() >= 400 ) {
return true;
}
if ($exception instanceof Exception\ServiceResponseException) {
if ($exception->getStatusCode() >= 400) {
return true;
}
}
if ($exception instanceof ConnectException) {
return true;
}
return false;
};
}
public function retryDelay() {
return function ($numberOfRetries) {
return 1000 * $numberOfRetries;
};
}
public function commandToRequestTransformer(CommandInterface $command)
{
$this->action = $command->GetName();
$this->operation = $this->api[$this->action];
$transformer = new CommandToRequestTransformer($this->cosConfig, $this->operation);
$seri = new Serializer($this->desc);
$request = $seri($command);
$request = $transformer->bucketStyleTransformer($command, $request);
$request = $transformer->uploadBodyTransformer($command, $request);
$request = $transformer->metadataTransformer($command, $request);
$request = $transformer->queryStringTransformer($command, $request);
$request = $transformer->headerTransformer($command, $request);
$request = $transformer->md5Transformer($command, $request);
$request = $transformer->specialParamTransformer($command, $request);
$request = $transformer->ciParamTransformer($command, $request);
$request = $transformer->cosDomain2CiTransformer($command, $request);
return $request;
}
public function responseToResultTransformer(ResponseInterface $response, RequestInterface $request, CommandInterface $command)
{
$transformer = new ResultTransformer($this->cosConfig, $this->operation);
$transformer->writeDataToLocal($command, $request, $response);
$deseri = new Deserializer($this->desc, true);
$result = $deseri($response, $request, $command);
$result = $transformer->metaDataTransformer($command, $response, $result);
$result = $transformer->extraHeadersTransformer($command, $request, $result);
$result = $transformer->selectContentTransformer($command, $result);
$result = $transformer->ciContentInfoTransformer($command, $result);
return $result;
}
public function __destruct() {
}
public function __call($method, array $args) {
try {
$rt = parent::__call(ucfirst($method), $args);
return $rt;
} catch (\Exception $e) {
$previous = $e->getPrevious();
if ($previous !== null) {
throw $previous;
} else {
throw $e;
}
}
}
public function getApi() {
return $this->api;
}
private function getCosConfig() {
return $this->cosConfig;
}
private function createPresignedUrl(RequestInterface $request, $expires) {
return $this->signature->createPresignedUrl($request, $expires);
}
public function getPresignedUrl($method, $args, $expires = "+30 minutes") {
$command = $this->getCommand($method, $args);
$request = $this->commandToRequestTransformer($command);
return $this->createPresignedUrl($request, $expires);
}
public function getObjectUrl($bucket, $key, $expires = "+30 minutes", array $args = array()) {
$command = $this->getCommand('GetObject', $args + array('Bucket' => $bucket, 'Key' => $key));
$request = $this->commandToRequestTransformer($command);
return $this->createPresignedUrl($request, $expires)->__toString();
}
public function getObjectUrlWithoutSign($bucket, $key, array $args = array()) {
$command = $this->getCommand('GetObject', $args + array('Bucket' => $bucket, 'Key' => $key));
$request = $this->commandToRequestTransformer($command);
return $request->getUri()->__toString();
}
public function upload($bucket, $key, $body, $options = array()) {
$body = Psr7\Utils::streamFor($body);
$options['Retry'] = $this->cosConfig['retry'];
$options['PartSize'] = isset($options['PartSize']) ? $options['PartSize'] : MultipartUpload::DEFAULT_PART_SIZE;
if ($body->getSize() < $options['PartSize']) {
$rt = $this->putObject(array(
'Bucket' => $bucket,
'Key' => $key,
'Body' => $body,
) + $options);
}
else {
$multipartUpload = new MultipartUpload($this, $body, array(
'Bucket' => $bucket,
'Key' => $key,
) + $options);
$rt = $multipartUpload->performUploading();
}
return $rt;
}
public function download($bucket, $key, $saveAs, $options = array()) {
$options['PartSize'] = isset($options['PartSize']) ? $options['PartSize'] : RangeDownload::DEFAULT_PART_SIZE;
$contentLength = 0;
$versionId = isset($options['VersionId']) ? $options['VersionId'] : '';
$rt = $this->headObject(array(
'Bucket'=>$bucket,
'Key'=>$key,
'VersionId'=>$versionId,
)
);
$contentLength = $rt['ContentLength'];
$resumableJson = [
'LastModified' => $rt['LastModified'],
'ContentLength' => $rt['ContentLength'],
'ETag' => $rt['ETag'],
'Crc64ecma' => $rt['Crc64ecma']
];
$options['ResumableJson'] = $resumableJson;
if ($contentLength < $options['PartSize']) {
$rt = $this->getObject(array(
'Bucket' => $bucket,
'Key' => $key,
'SaveAs' => $saveAs,
) + $options);
} else {
$rangeDownload = new RangeDownload($this, $contentLength, $saveAs, array(
'Bucket' => $bucket,
'Key' => $key,
) + $options);
$rt = $rangeDownload->performDownloading();
}
return $rt;
}
public function resumeUpload($bucket, $key, $body, $uploadId, $options = array()) {
$body = Psr7\Utils::streamFor($body);
$options['PartSize'] = isset($options['PartSize']) ? $options['PartSize'] : MultipartUpload::DEFAULT_PART_SIZE;
$multipartUpload = new MultipartUpload($this, $body, array(
'Bucket' => $bucket,
'Key' => $key,
'UploadId' => $uploadId,
) + $options);
$rt = $multipartUpload->resumeUploading();
return $rt;
}
public function copy($bucket, $key, $copySource, $options = array()) {
$options['PartSize'] = isset($options['PartSize']) ? $options['PartSize'] : Copy::DEFAULT_PART_SIZE;
// set copysource client
$sourceConfig = $this->rawCosConfig;
$sourceConfig['region'] = $copySource['Region'];
$cosSourceClient = new Client($sourceConfig);
$copySource['VersionId'] = isset($copySource['VersionId']) ? $copySource['VersionId'] : '';
$rt = $cosSourceClient->headObject(
array('Bucket'=>$copySource['Bucket'],
'Key'=>$copySource['Key'],
'VersionId'=>$copySource['VersionId'],
)
);
$contentLength = $rt['ContentLength'];
// sample copy
if ($contentLength < $options['PartSize']) {
$rt = $this->copyObject(array(
'Bucket' => $bucket,
'Key' => $key,
'CopySource' => "{$copySource['Bucket']}.cos.{$copySource['Region']}.myqcloud.com/". urlencode("{$copySource['Key']}")."?versionId={$copySource['VersionId']}",
) + $options
);
return $rt;
}
// multi part copy
$copySource['ContentLength'] = $contentLength;
$copy = new Copy($this, $copySource, array(
'Bucket' => $bucket,
'Key' => $key
) + $options
);
return $copy->copy();
}
public function doesBucketExist($bucket, array $options = array())
{
try {
$this->HeadBucket(array(
'Bucket' => $bucket));
return true;
} catch (\Exception $e){
return false;
}
}
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 explodeKey($key) {
// Remove a leading slash if one is found
$split_key = explode('/', $key && $key[0] == '/' ? substr($key, 1) : $key);
// Remove empty element
$split_key = array_filter($split_key, function($var) {
return !($var == '' || $var == null);
});
$final_key = implode("/", $split_key);
if (substr($key, -1) == '/') {
$final_key = $final_key . '/';
}
return $final_key;
}
public static function handleSignature($secretId, $secretKey, $options) {
return function (callable $handler) use ($secretId, $secretKey, $options) {
return new SignatureMiddleware($handler, $secretId, $secretKey, $options);
};
}
public static function handleErrors() {
return function (callable $handler) {
return new ExceptionMiddleware($handler);
};
}
}

View File

@ -0,0 +1,410 @@
<?php
namespace Qcloud\Cos;
use http\Exception\BadUrlException;
use Psr\Http\Message\RequestInterface;
use GuzzleHttp\Command\CommandInterface;
use GuzzleHttp\Psr7\Uri;
use InvalidArgumentException;
use Psr\Http\Message\UriInterface;
class CommandToRequestTransformer {
private $config;
private $operation;
public function __construct( $config, $operation ) {
$this->config = $config;
$this->operation = $operation;
}
// format bucket style
public function bucketStyleTransformer( CommandInterface $command, RequestInterface $request ) {
$action = $command->getName();
if ($action == 'ListBuckets') {
$uri = "service.cos.myqcloud.com";
if ($this->config['endpoint'] != null) {
$uri = $this->config['endpoint'];
}
if ($this->config['domain'] != null) {
$uri = $this->config['domain'];
}
if ($this->config['ip'] != null) {
$uri = $this->config['ip'];
if ($this->config['port'] != null) {
$uri = $this->config['ip'] . ":" . $this->config['port'];
}
}
return $request->withUri(new Uri($this->config['schema']."://". $uri. "/"));
}
$operation = $this->operation;
$bucketname = $command['Bucket'];
$appId = $this->config['appId'];
if ( $appId != null && endWith( $bucketname, '-'.$appId ) == false ) {
$bucketname = $bucketname.'-'.$appId;
}
$command['Bucket'] = $bucketname;
$uri = $operation['uri'];
// Hoststyle is used by default
// Pathstyle
if ( $this->config['pathStyle'] != true ) {
if ( isset( $operation['parameters']['Bucket'] ) && $command->hasParam( 'Bucket' ) ) {
$uri = str_replace( '{Bucket}', '', $uri );
}
if ( isset( $operation['parameters']['Key'] ) && $command->hasParam( 'Key' ) ) {
$uri = str_replace( '{/Key*}', encodeKey( $command['Key'] ), $uri );
}
}
if ($this->config['endpoint'] == null) {
$this->config['endpoint'] = "myqcloud.com";
}
$domain_type = '.cos.';
if ($action == 'PutBucketImageStyle' || $action == 'GetBucketImageStyle' || $action == 'DeleteBucketImageStyle'
|| $action == 'PutBucketGuetzli' || $action == 'GetBucketGuetzli' || $action == 'DeleteBucketGuetzli'
|| $action == 'BindCiService' || $action == 'GetCiService' || $action == 'UnBindCiService'
|| $action == 'GetHotLink' || $action == 'AddHotLink'
|| $action == 'OpenOriginProtect' || $action == 'GetOriginProtect' || $action == 'CloseOriginProtect'
|| $action == 'OpenImageSlim' || $action == 'GetImageSlim' || $action == 'CloseImageSlim' ) {
$domain_type = '.pic.';
}
$origin_host = $this->config['allow_accelerate'] ?
$bucketname . $domain_type . 'accelerate' . '.' . $this->config['endpoint'] :
$bucketname . $domain_type . $this->config['region'] . '.' . $this->config['endpoint'];
// domain
if ( $this->config['domain'] != null ) {
$origin_host = $this->config['domain'];
}
$host = $origin_host;
if ( $this->config['ip'] != null ) {
$host = $this->config['ip'];
if ( $this->config['port'] != null ) {
$host = $this->config['ip'] . ':' . $this->config['port'];
}
}
$path = $this->config['schema'].'://'. $host . $uri;
$uri = new Uri( $path );
$query = $request->getUri()->getQuery();
if ( $uri->getQuery() != $query && $uri->getQuery() != '' ) {
$query = $uri->getQuery() . '&' . $request->getUri()->getQuery();
}
$uri = $uri->withQuery( $query );
$request = $request->withUri( $uri );
$request = $request->withHeader( 'Host', $origin_host );
return $request;
}
// format upload body
public function uploadBodyTransformer( CommandInterface $command, $request, $bodyParameter = 'Body', $sourceParameter = 'SourceFile' ) {
$operation = $this->operation;
if ( !isset( $operation['parameters']['Body'] ) ) {
return $request;
}
$source = isset( $command[$sourceParameter] ) ? $command[$sourceParameter] : null;
$body = isset( $command[$bodyParameter] ) ? $command[$bodyParameter] : null;
// 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 ) {
return $request;
} else {
throw new InvalidArgumentException("You must specify a non-null value for the {$bodyParameter} or {$sourceParameter} parameters.");
}
}
// update md5
public function md5Transformer( CommandInterface $command, $request ) {
$operation = $this->operation;
if ( isset( $operation['data']['contentMd5'] ) ) {
$request = $this->addMd5( $request );
}
if ( isset( $operation['parameters']['ContentMD5'] ) &&
isset( $command['ContentMD5'] ) ) {
$value = $command['ContentMD5'];
if ( $value != false ) {
$request = $this->addMd5( $request );
}
}
return $request;
}
// add Query string
public function queryStringTransformer( CommandInterface $command, $request ) {
$operation = $this->operation;
if ( isset( $command['Params'] ) ) {
$params = $command['Params'];
foreach ( $params as $key => $value ) {
$uri = $request->getUri();
$query = $uri->getQuery();
$uri = $uri->withQuery($query. "&" . urlencode($key) . "=" . $value );
$request = $request->withUri( $uri );
}
}
return $request;
}
// add Header string
public function headerTransformer( CommandInterface $command, $request ) {
$operation = $this->operation;
if ( isset( $command['Headers'] ) ) {
$headers = $command['Headers'];
foreach ( $headers as $key => $value ) {
$request = $request->withHeader( $key, $value);
}
}
return $request;
}
// add meta
public function metadataTransformer( CommandInterface $command, $request ) {
$operation = $this->operation;
if ( isset( $command['Metadata'] ) ) {
$meta = $command['Metadata'];
foreach ( $meta as $key => $value ) {
$request = $request->withHeader( 'x-cos-meta-' . $key, $value );
}
}
$request = headersMap( $command, $request );
return $request;
}
// count md5
private function addMd5( $request ) {
$body = $request->getBody();
if ( $body && $body->getSize() > 0 ) {
$md5 = base64_encode( md5( $body, true ) );
return $request->withHeader( 'Content-MD5', $md5 );
}
return $request;
}
// inventoryId
public function specialParamTransformer( CommandInterface $command, $request ) {
$action = $command->getName();
if ( $action == 'PutBucketInventory' ) {
$id = $command['Id'];
$uri = $request->getUri();
$query = $uri->getQuery();
$uri = $uri->withQuery( $query . '&Id='.$id );
return $request->withUri( $uri );
}
return $request;
}
public function ciParamTransformer( CommandInterface $command, $request ) {
$action = $command->getName();
if ( $action == 'GetObject' ) {
if(str_contains($uri = $request->getUri(), '%21') ) {
$uri = new Uri( str_replace('%21', '!', $uri) );
$request = $request->withUri( $uri );
}
if(isset($command['ImageHandleParam']) && $command['ImageHandleParam']){
$uri = $request->getUri();
$query = $uri->getQuery();
if($query){
$query .= "&" . urlencode($command['ImageHandleParam']);
}else{
$query .= urlencode($command['ImageHandleParam']);
}
$uri = $uri->withQuery($query);
$request = $request->withUri( $uri );
}
}
return $request;
}
public function cosDomain2CiTransformer(CommandInterface $command, $request) {
$action = $command->getName();
if(key_exists($action, array(
'DescribeMediaBuckets' => 1,
'DescribeDocProcessBuckets' =>1,
'GetPicBucketList' =>1,
'GetAiBucketList' =>1,
))) {
$origin_host = "ci.{$this->config['region']}.myqcloud.com";
$host = $origin_host;
if ($this->config['ip'] != null) {
$host = $this->config['ip'];
if ($this->config['port'] != null) {
$host = $this->config['ip'] . ":" . $this->config['port'];
}
}
$path = $this->config['schema'].'://'. $host . $request->getUri()->getPath();
$uri = new Uri( $path );
$query = $request->getUri()->getQuery();
$uri = $uri->withQuery( $query );
$request = $request->withUri( $uri );
$request = $request->withHeader( 'Host', $origin_host );
return $request;
}
$ciActions = array(
'DetectText' => 1,
'CreateMediaTranscodeJobs' => 1,
'CreateMediaJobs' => 1,
'DescribeMediaJob' => 1,
'DescribeMediaJobs' => 1,
'CreateMediaSnapshotJobs' => 1,
'CreateMediaConcatJobs' => 1,
'DetectAudio' => 1,
'GetDetectAudioResult' => 1,
'GetDetectTextResult' => 1,
'DetectVideo' => 1,
'GetDetectVideoResult' => 1,
'DetectDocument' => 1,
'GetDetectDocumentResult' => 1,
'CreateDocProcessJobs' => 1,
'DescribeDocProcessQueues' => 1,
'DescribeDocProcessJob' => 1,
'GetDescribeDocProcessJobs' => 1,
'DetectImages' => 1,
'GetDetectImageResult' => 1,
'DetectVirus' => 1,
'GetDetectVirusResult' => 1,
'CreateMediaVoiceSeparateJobs' => 1,
'DescribeMediaVoiceSeparateJob' => 1,
'DetectWebpage' => 1,
'GetDetectWebpageResult' => 1,
'DescribeMediaQueues' => 1,
'UpdateMediaQueue' => 1,
'CreateMediaSmartCoverJobs' => 1,
'CreateMediaVideoProcessJobs' => 1,
'CreateMediaVideoMontageJobs' => 1,
'CreateMediaAnimationJobs' => 1,
'CreateMediaPicProcessJobs' => 1,
'CreateMediaSegmentJobs' => 1,
'CreateMediaVideoTagJobs' => 1,
'CreateMediaSuperResolutionJobs' => 1,
'CreateMediaSDRtoHDRJobs' => 1,
'CreateMediaDigitalWatermarkJobs' => 1,
'CreateMediaExtractDigitalWatermarkJobs' => 1,
'DetectLiveVideo' => 1,
'CancelLiveVideoAuditing' => 1,
'TriggerWorkflow' => 1,
'GetWorkflowInstances' => 1,
'GetWorkflowInstance' => 1,
'CreateMediaSnapshotTemplate' => 1,
'UpdateMediaSnapshotTemplate' => 1,
'CreateMediaTranscodeTemplate' => 1,
'UpdateMediaTranscodeTemplate' => 1,
'CreateMediaHighSpeedHdTemplate' => 1,
'UpdateMediaHighSpeedHdTemplate' => 1,
'CreateMediaAnimationTemplate' => 1,
'UpdateMediaAnimationTemplate' => 1,
'CreateMediaConcatTemplate' => 1,
'UpdateMediaConcatTemplate' => 1,
'CreateMediaVideoProcessTemplate' => 1,
'UpdateMediaVideoProcessTemplate' => 1,
'CreateMediaVideoMontageTemplate' => 1,
'UpdateMediaVideoMontageTemplate' => 1,
'CreateMediaVoiceSeparateTemplate' => 1,
'UpdateMediaVoiceSeparateTemplate' => 1,
'CreateMediaSuperResolutionTemplate' => 1,
'UpdateMediaSuperResolutionTemplate' => 1,
'CreateMediaPicProcessTemplate' => 1,
'UpdateMediaPicProcessTemplate' => 1,
'CreateMediaWatermarkTemplate' => 1,
'UpdateMediaWatermarkTemplate' => 1,
'DescribeMediaTemplates' => 1,
'DescribeWorkflow' => 1,
'DeleteWorkflow' => 1,
'CreateInventoryTriggerJob' => 1,
'DescribeInventoryTriggerJobs' => 1,
'DescribeInventoryTriggerJob' => 1,
'CancelInventoryTriggerJob' => 1,
'CreateMediaNoiseReductionJobs' => 1,
'ImageSearchOpen' => 1,
'UpdateDocProcessQueue' => 1,
'CreateMediaQualityEstimateJobs' => 1,
'CreateMediaStreamExtractJobs' => 1,
'OpenFileProcessService' => 1,
'GetFileProcessQueueList' => 1,
'UpdateFileProcessQueue' => 1,
'CreateFileHashCodeJobs' => 1,
'GetFileHashCodeResult' => 1,
'CreateFileUncompressJobs' => 1,
'GetFileUncompressResult' => 1,
'CreateFileCompressJobs' => 1,
'GetFileCompressResult' => 1,
'CreateM3U8PlayListJobs' => 1,
'GetPicQueueList' => 1,
'UpdatePicQueue' => 1,
'OpenAiService' => 1,
'GetAiQueueList' => 1,
'UpdateAiQueue' => 1,
'CreateMediaTranscodeProTemplate' => 1,
'UpdateMediaTranscodeProTemplate' => 1,
'CreateVoiceTtsTemplate' => 1,
'UpdateVoiceTtsTemplate' => 1,
'CreateMediaSmartCoverTemplate' => 1,
'UpdateMediaSmartCoverTemplate' => 1,
'CreateVoiceSpeechRecognitionTemplate' => 1,
'UpdateVoiceSpeechRecognitionTemplate' => 1,
'CreateVoiceTtsJobs' => 1,
'CreateAiTranslationJobs' => 1,
'CreateVoiceSpeechRecognitionJobs' => 1,
'CreateAiWordsGeneralizeJobs' => 1,
'CreateMediaVideoEnhanceJobs' => 1,
'CreateMediaVideoEnhanceTemplate' => 1,
'UpdateMediaVideoEnhanceTemplate' => 1,
);
if (key_exists($action, $ciActions)) {
// 万象接口需要httpshttp方式报错
if($this->config['schema'] !== 'https') {
$e = new Exception\CosException('CI request schema must be "https", instead of "http"');
$e->setExceptionCode('Invalid Argument');
throw $e;
}
$bucketname = $command['Bucket'];
$appId = $this->config['appId'];
if ( $appId != null && endWith( $bucketname, '-'.$appId ) == false ) {
$bucketname = $bucketname.'-'.$appId;
}
$command['Bucket'] = $bucketname;
$domain_type = '.ci.';
$origin_host = $bucketname . $domain_type . $this->config['region'] . '.' . $this->config['endpoint'];
$host = $origin_host;
if ( $this->config['ip'] != null ) {
$host = $this->config['ip'];
if ( $this->config['port'] != null ) {
$host = $this->config['ip'] . ':' . $this->config['port'];
}
}
$path = $this->config['schema'].'://'. $host . $request->getUri()->getPath();
$uri = new Uri( $path );
$query = $request->getUri()->getQuery();
$uri = $uri->withQuery( $query );
$request = $request->withUri( $uri );
$request = $request->withHeader( 'Host', $origin_host );
}
return $request;
}
public function __destruct() {
}
}

69
vendor/qcloud/cos-sdk-v5/src/Common.php vendored Normal file
View File

@ -0,0 +1,69 @@
<?php
namespace Qcloud\Cos;
function region_map($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'
);
if (isset($regionmap[$region])) {
return $regionmap[$region];
}
return $region;
}
function encodeKey($key)
{
return str_replace('%2F', '/', rawurlencode($key));
}
function endWith($haystack, $needle)
{
$length = strlen($needle);
if ($length == 0) {
return true;
}
return (substr($haystack, -$length) === $needle);
}
function startWith($haystack, $needle)
{
$length = strlen($needle);
if ($length == 0) {
return true;
}
return (substr($haystack, 0, $length) === $needle);
}
function headersMap($command, $request)
{
$headermap = array(
'TransferEncoding' => 'Transfer-Encoding',
'ChannelId' => 'x-cos-channel-id'
);
foreach ($headermap as $key => $value) {
if (isset($command[$key])) {
$request = $request->withHeader($value, $command[$key]);
}
}
return $request;
}
if (!function_exists('str_contains')) {
function str_contains($haystack, $needle)
{
return strpos($haystack, $needle) !== false;
}
}

140
vendor/qcloud/cos-sdk-v5/src/Copy.php vendored Normal file
View File

@ -0,0 +1,140 @@
<?php
namespace Qcloud\Cos;
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'];
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,5 @@
<?php
namespace Qcloud\Cos\Exception;
class CosException extends ServiceResponseException {}

View File

@ -0,0 +1,189 @@
<?php
namespace Qcloud\Cos\Exception;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
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
*/
public function setResponse(ResponseInterface $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')[0];
}
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;
}
}

View File

@ -0,0 +1,71 @@
<?php
namespace Qcloud\Cos;
use Qcloud\Cos\Exception\ServiceResponseException;
use GuzzleHttp\Promise\PromiseInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\Exception\RequestException;
class ExceptionMiddleware {
private $nextHandler;
protected $parser;
protected $defaultException;
/**
* @param callable $nextHandler Next handler to invoke.
*/
public function __construct(callable $nextHandler) {
$this->nextHandler = $nextHandler;
$this->parser = new ExceptionParser();
$this->defaultException = 'Qcloud\Cos\Exception\ServiceResponseException';
}
/**
* @param RequestInterface $request
* @param array $options
*
* @return PromiseInterface
*/
public function __invoke(RequestInterface $request, array $options) {
$fn = $this->nextHandler;
return $fn($request, $options)->then(
function (ResponseInterface $response) use ($request) {
return $this->handle($request, $response);
}
);
}
public function handle(RequestInterface $request, ResponseInterface $response) {
$code = $response->getStatusCode();
if ($code < 400) {
return $response;
}
//throw RequestException::create($request, $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;
throw $this->createException($className, $request, $response, $parts);
}
protected function createException($className, RequestInterface $request, ResponseInterface $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;
}
}

View File

@ -0,0 +1,112 @@
<?php
namespace Qcloud\Cos;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
/**
* Parses default XML exception responses
*/
class ExceptionParser {
public function parse(RequestInterface $request, ResponseInterface $response) {
$data = array(
'code' => null,
'message' => null,
//'type' => $response->isClientError() ? 'client' : 'server',
'type' => 'client',
'request_id' => null,
'parsed' => null
);
$body = strval($response->getBody());
if (empty($body)) {
$this->parseHeaders($request, $response, $data);
return $data;
}
try {
$xml = new \SimpleXMLElement(mb_convert_encoding($body, 'UTF-8'));
$this->parseBody($xml, $data);
return $data;
} catch (\Exception $e) {
$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 ResponseInterface $response The response from the request
* @param array $data The current set of exception data
*/
protected function parseHeaders(RequestInterface $request, ResponseInterface $response, array &$data) {
$data['message'] = $response->getStatusCode() . ' ' . $response->getReasonPhrase();
$requestId = $response->getHeader('x-cos-request-id');
if (isset($requestId[0])) {
$requestId = $requestId[0];
$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->getUri()->getPath(), '/'));
$host = explode('.', $request->getUri()->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];
}
}
}

View File

@ -0,0 +1,87 @@
<?php
namespace Qcloud\Cos\ImageParamTemplate;
class BlindWatermarkTemplate extends ImageTemplate {
private $markType;
private $type;
private $image;
private $text;
private $level;
public function __construct() {
parent::__construct();
$this->markType = 3;
$this->type = "";
$this->image = "";
$this->text = "";
$this->level = "";
}
public function setPick() {
$this->markType = 4;
}
public function setType($value) {
$this->type = "/type/" . $value;
}
public function setImage($value) {
$this->image = "/image/" . $this->ciBase64($value);
}
public function setText($value) {
$this->text = "/text/" . $this->ciBase64($value);
}
public function setLevel($value) {
$this->level = "/level/" . $value;
}
public function getType() {
return $this->type;
}
public function getImage() {
return $this->image;
}
public function getText() {
return $this->text;
}
public function getLevel() {
return $this->level;
}
public function queryString() {
$head = "watermark/$this->markType";
$res = "";
if($this->type){
$res .= $this->type;
}
if($this->image){
$res .= $this->image;
}
if($this->text){
$res .= $this->text;
}
if($this->level){
$res .= $this->level;
}
if($res){
$res = $head . $res;
}
return $res;
}
public function resetRule() {
$this->markType = 3;
$this->type = "";
$this->image = "";
$this->text = "";
$this->level = "";
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace Qcloud\Cos\ImageParamTemplate;
class CIParamTransformation extends ImageTemplate{
private $tranParams;
private $tranString;
private $spilt;
public function __construct($spilt = "|") {
parent::__construct();
$this->spilt = $spilt;
$this->tranParams = array();
$this->tranString = "";
}
public function addRule(ImageTemplate $template) {
if($template->queryString()){
$this->tranParams[] = $template->queryString();
}
}
public function queryString() {
if($this->tranParams) {
$this->tranString = implode($this->spilt, $this->tranParams);
}
return $this->tranString;
}
public function resetRule() {
$this->tranParams = array();
$this->tranString = "";
}
public function defineRule($value) {
$this->tranParams[] = $value;
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace Qcloud\Cos\ImageParamTemplate;
class CIProcessTransformation extends ImageTemplate{
private $tranParams = array();
private $tranString;
public function __construct($ciProcess) {
parent::__construct();
$this->tranParams['ci-process'] = $ciProcess;
$this->tranString = "";
}
public function addParam($name, $value, $base64 = false) {
if(is_string($name) && strlen($name) > 0){
if($base64) {
$value = $this->ciBase64($value);
}
$this->tranParams[$name] = $value;
}
}
public function queryString() {
if($this->tranParams) {
$this->tranString = http_build_query($this->tranParams);
}
return $this->tranString;
}
}

View File

@ -0,0 +1,374 @@
<?php
namespace Qcloud\Cos\ImageParamTemplate;
/**
* Class ImageMogrTemplate imageMogr2 接口参数
* @package Qcloud\Cos\ImageParamTemplate
*/
class ImageMogrTemplate extends ImageTemplate
{
private $tranParams;
private $tranString;
public function __construct() {
parent::__construct();
$this->tranParams = array();
$this->tranString = "";
}
/**
* 指定图片的宽高为原图的 Scale%
* @param $widthScale
*/
public function thumbnailByScale($widthScale) {
$this->tranParams[] = "/thumbnail/!" . $widthScale . "p";
}
/**
* 指定图片的宽为原图的 Scale%,高度不变
* @param $heightScale
*/
public function thumbnailByWidthScale($heightScale) {
$this->tranParams[] = "/thumbnail/!" . $heightScale . "px";
}
/**
* 指定图片的高为原图的 Scale%,宽度不变
* @param $scale
*/
public function thumbnailByHeightScale($scale) {
$this->tranParams[] = "/thumbnail/!x" . $scale . "p";
}
/**
* 指定目标图片宽度为 Width高度等比缩放
* @param $width
*/
public function thumbnailByWidth($width) {
$this->tranParams[] = "/thumbnail/" . $width . "x";
}
/**
* 指定目标图片高度为 Height宽度等比缩放
* @param $height
*/
public function thumbnailByHeight($height) {
$this->tranParams[] = "/thumbnail/x" . $height;
}
/**
* 限定缩略图的宽度和高度的最大值分别为 Width 和 Height进行等比缩放
* @param $maxW
* @param $maxH
*/
public function thumbnailByMaxWH($maxW, $maxH) {
$this->tranParams[] = "/thumbnail/" . $maxW . "x" . $maxH;
}
/**
* 限定缩略图的宽度和高度的最小值分别为 Width 和 Height进行等比缩放
* @param $minW
* @param $minH
*/
public function thumbnailByMinWH($minW, $minH) {
$this->tranParams[] = "/thumbnail/!" . $minW . "x" . $minH . "r" ;
}
/**
* 忽略原图宽高比例,指定图片宽度为 Width高度为 Height强行缩放图片可能导致目标图片变形
* @param $width
* @param $height
*/
public function thumbnailByWH($width, $height) {
$this->tranParams[] = "/thumbnail/" . $width . "x" . $height . "!";
}
/**
* 限定缩略图的宽度和高度的最大值分别为 Width 和 Height进行等比缩小比例值为宽缩放比和高缩放比的较小值如果目标宽都大于原图宽则不变
* @param $width
* @param $height
*/
public function thumbnailEqualRatioReduceByWH($width, $height) {
$this->tranParams[] = "/thumbnail/{$width}x{$height}>";
}
/**
* 限定缩略图的宽度和高度的最大值分别为 Width 和 Height进行等比放大比例值为宽缩放比和高缩放比的较小值。如果目标宽(高)小于原图宽(高),则不变
* @param $width
* @param $height
*/
public function thumbnailEqualRatioEnlargeByWH($width, $height) {
$this->tranParams[] = "/thumbnail/{$width}x{$height}<";
}
/**
* 等比缩放图片,缩放后的图像,总像素数量不超过 $pixel
* @param $pixel
*/
public function thumbnailByPixel($pixel) {
$this->tranParams[] = "/thumbnail/" . $pixel . "@";
}
/**
* 将原图缩放为指定 Width 和 Height 的矩形内的最大图片,之后使用 color 参数指定的颜色居中填充空白部分取值0或10代表不使用 pad 模式1代表使用 pad 模式
* @param $is
*/
public function pad($is) {
$this->tranParams[] = "/pad/{$is}";
}
/**
* 填充颜色,缺省为白色,需设置为十六进制 RGB 格式(如 #FF0000详情参考 RGB 编码表,需经过 URL 安全的 Base64 编码,默认值为 #3D3D3D
* @param $rgb
*/
public function color($rgb) {
$rgb = $this->ciBase64($rgb);
$this->tranParams[] = "/color/{$rgb}";
}
/**
* 当处理参数中携带此参数时,针对文件过大、参数超限等导致处理失败的场景,会直接返回原图而不报错
*/
public function ignoreError() {
$this->tranParams[] = "/ignore-error/1";
}
/**
* 普通裁剪参数说明 操作名称cut
* @param $width
* @param $height
* @param $dx
* @param $dy
*/
public function cut($width, $height, $dx, $dy) {
$this->tranParams[] = "/cut/" . $width . "x" . "$height" . "x" . $dx . "x" . $dy;
}
/**
* 指定目标图片宽度为 Width高度不变。Width 取值范围应大于0小于原图宽度
* @param $width
* @param string $gravity 指定操作的起点位置
*/
public function cropByWidth($width, $gravity = "") {
$temp = "/crop/" . $width . "x";
if($gravity){
$temp .= "/gravity/" . $gravity;
}
$this->tranParams[] = $temp;
}
/**
* 指定目标图片高度为 Height宽度不变。Height 取值范围应大于0小于原图高度
* @param $height
* @param string $gravity 指定操作的起点位置
*/
public function cropByHeight($height, $gravity = "") {
$temp = "/crop/x" . $height;
if($gravity){
$temp .= "/gravity/" . $gravity;
}
$this->tranParams[] = $temp;
}
/**
* 指定目标图片宽度为 Width高度为 Height 。Width 和 Height 取值范围都应大于0小于原图宽度/高度
* @param $width
* @param $height
* @param string $gravity 指定操作的起点位置
*/
public function cropByWH($width, $height, $gravity = "") {
$temp = "/crop/" . $width . "x" . $height;
if($gravity){
$temp .= "/gravity/" . $gravity;
}
$this->tranParams[] = $temp;
}
/**
* 内切圆裁剪功能radius 是内切圆的半径取值范围为大于0且小于原图最小边一半的整数。内切圆的圆心为图片的中心。图片格式为 gif 时,不支持该参数。
* @param $radius
*/
public function iradius($radius) {
$this->tranParams[] = "/iradius/" . $radius;
}
/**
* 圆角裁剪功能radius 为图片圆角边缘的半径取值范围为大于0且小于原图最小边一半的整数。圆角与原图边缘相切。图片格式为 gif 时,不支持该参数。
* @param $radius
*/
public function rradius($radius) {
$this->tranParams[] = "/rradius/" . $radius;
}
/**
* 基于图片中的人脸位置进行缩放裁剪。目标图片的宽度为 Width、高度为 Height。
* @param $width
* @param $height
*/
public function scrop($width, $height) {
$this->tranParams[] = "/scrop/" . $width . "x" . $height;
}
/**
* 普通旋转图片顺时针旋转角度取值范围0 - 360默认不旋转。
* @param $degree
*/
public function rotate($degree) {
$this->tranParams[] = "/rotate/" . $degree;
}
/**
* 自适应旋转:根据原图 EXIF 信息将图片自适应旋转回正。
*/
public function autoOrient() {
$this->tranParams[] = "/auto-orient";
}
/**
* 镜像翻转flip 值为 vertical 表示垂直翻转horizontal 表示水平翻转
* @param $flip
*/
public function flip($flip) {
$this->tranParams[] = "/flip/" . $flip;
}
/**
* 格式转换目标缩略图的图片格式可为jpgbmpgifpngwebpyjpeg 等,其中 yjpeg 为数据万象针对 jpeg 格式进行的优化,本质为 jpg 格式;缺省为原图格式。
* @param $format
*/
public function format($format) {
$this->tranParams[] = "/format/" . $format;
}
/**
* gif 格式优化:只针对原图为 gif 格式,对 gif 图片格式进行的优化,降帧降颜色。分为以下两种情况:
* FrameNumber=1则按照默认帧数30处理如果图片帧数大于该帧数则截取。
* FrameNumber 取值( 1,100 ],则将图片压缩到指定帧数 FrameNumber
* @param $frameNumber
*/
public function gifOptimization($frameNumber) {
$this->tranParams[] = "/cgif/" . $frameNumber;
}
/**
* 输出为渐进式 jpg 格式。Mode 可为0或1。0表示不开启渐进式1表示开启渐进式。该参数仅在输出图片格式为 jpg 格式时有效。如果输出非 jpg 图片格式会忽略该参数默认值0。
* @param $mode
*/
public function jpegInterlaceMode($mode) {
$this->tranParams[] = "/interlace/" . $mode;
}
/**
* 图片的绝对质量取值范围0 - 100默认值为原图质量取原图质量和指定质量的最小值<Quality>后面加“!”表示强制使用指定值例如90!。
* @param $value
* @param int $force
*/
public function quality($value, $force = 0) {
$temp = "/quality/" . $value;
if($force){
$temp .= "!";
}
$this->tranParams[] = $temp;
}
/**
* 图片的最低质量取值范围0 - 100设置结果图的质量参数最小值。
* 例如原图质量为85将 lquality 设置为80后处理结果图的图片质量为85。
* 例如原图质量为60将 lquality 设置为80后处理结果图的图片质量会被提升至80。
* @param $value
*/
public function lowestQuality($value) {
$this->tranParams[] = "/lquality/" . $value;
}
/**
* 图片的相对质量取值范围0 - 100数值以原图质量为标准。例如原图质量为80将 rquality 设置为80后得到处理结果图的图片质量为6480x80%)。
* @param $value
*/
public function relativelyQuality($value) {
$this->tranParams[] = "/rquality/" . $value;
}
/**
* 高斯模糊
* @param $radius integer|float 模糊半径取值范围为1 - 50
* @param $sigma integer|float 正态分布的标准差必须大于0
*/
public function blur($radius, $sigma) {
$this->tranParams[] = "/blur/" . $radius . "x" . $sigma;
}
/**
* 图片亮度调节功能value 为亮度参数值,取值范围为[-100, 100]的整数。
* 取值0降低图片亮度。
* 取值 = 0不调整图片亮度。
* 取值0提高图片亮度。
* @param $value
*/
public function bright($value) {
$this->tranParams[] = "/bright/" . $value;
}
/**
* 图片对比度调节功能value 为对比度参数值,取值范围为[-100, 100]的整数。
* 取值0降低图片对比度。
* 取值 = 0不调整图片对比度。
* 取值0提高图片对比度。
* @param $value
*/
public function contrast($value) {
$this->tranParams[] = "/contrast/" . $value;
}
/**
* 图片锐化功能value 为锐化参数值取值范围为10 - 300间的整数推荐使用70。参数值越大锐化效果越明显。
* @param $value
*/
public function sharpen($value) {
$this->tranParams[] = "/sharpen/" . $value;
}
/**
* 将图片设置为灰度图。 value 取值为0表示不改变图片。 value 取值为1表示将图片变为灰度图。
* @param $value
*/
public function grayscale($value) {
$this->tranParams[] = "/grayscale/" . $value;
}
/**
* 去除图片元信息,包括 exif 信息
*/
public function strip() {
$this->tranParams[] = "/strip";
}
/**
* 限制图片转换后的大小支持以兆字节m和千字节k为单位
* 1. 仅支持 JPG 格式的图片,可以用于限制处理后图片的大小
* 2. 若在尾部加上!表示用处理后的图片大小与原图大小做比较如果处理后的图片比原图小则返回处理后的图片否则返回原图。例如examplebucket-1250000000.cos.ap-shanghai.myqcloud.com/picture.jpg?imageMogr2/size-limit/15k!
* 3. 建议搭配strip参数使用去除图片的一些冗余信息会有更好的效果。例如examplebucket-1250000000.cos.ap-shanghai.myqcloud.com/picture.jpg?imageMogr2/strip/format/png/size-limit/15k!
* @param $value
* @param int $compare
*/
public function sizeLimit($value, $compare = 0) {
$temp = "/size-limit/" . $value;
if($compare){
$temp .= "!";
}
$this->tranParams[] = $temp;
}
public function queryString() {
if($this->tranParams) {
$this->tranString = "imageMogr2" . implode("", $this->tranParams);
}
return $this->tranString;
}
public function resetRule() {
$this->tranString = "";
$this->tranParams = array();
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace Qcloud\Cos\ImageParamTemplate;
class ImageQrcodeTemplate extends ImageTemplate
{
private $mode;
public function __construct() {
parent::__construct();
$this->mode = "";
}
public function setMode($mode) {
$this->mode = "/cover/" . $mode;
}
public function getMode() {
return $this->mode;
}
public function queryString() {
$head = "QRcode";
$res = "";
if($this->mode) {
$res .= $this->mode;
}
if($res) {
$res = $head . $res;
}
return $res;
}
public function resetRule() {
$this->mode = "";
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace Qcloud\Cos\ImageParamTemplate;
class ImageStyleTemplate extends ImageTemplate
{
private $style;
public function __construct() {
parent::__construct();
$this->style = "";
}
public function setStyle($styleName) {
$this->style = "style/" . $styleName;
}
public function getStyle() {
return $this->style;
}
public function queryString() {
$res = "";
if($this->style) {
$res = $this->style;
}
return $res;
}
public function resetRule() {
$this->style = "";
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace Qcloud\Cos\ImageParamTemplate;
class ImageTemplate
{
public function __construct() {
}
public function queryString() {
return "";
}
public function ciBase64($value) {
return str_replace("/", "_", str_replace("+", "-", base64_encode($value)));
}
}

View File

@ -0,0 +1,115 @@
<?php
namespace Qcloud\Cos\ImageParamTemplate;
/**
* Parses default XML exception responses
*/
class ImageViewTemplate extends ImageTemplate
{
private $mode;
private $width;
private $height;
private $format;
private $quality;
private $ignoreError;
public function __construct() {
parent::__construct();
$this->mode = "";
$this->width = "";
$this->height = "";
$this->format = "";
$this->quality = "";
$this->ignoreError = "";
}
public function setMode($value) {
$this->mode = "/" . $value;
}
public function setWidth($value) {
$this->width = "/w/" . $value;
}
public function setHeight($value) {
$this->height = "/h/" . $value;
}
public function setFormat($value) {
$this->format = "/format/" . $value;
}
public function setQuality($qualityType, $qualityValue, $force = 0) {
if($qualityType == 1){
$this->quality = "/q/$qualityValue" ;
if($force){
$this->quality .= "!";
}
}else if($qualityType == 2){
$this->quality = "/rq/$qualityValue" ;
}else if ($qualityType == 3){
$this->quality = "/lq/$qualityValue" ;
}
}
public function ignoreError() {
$this->ignoreError = '/ignore-error/1';
}
public function getMode() {
return $this->mode;
}
public function getWidth() {
return $this->width;
}
public function getHeight() {
return $this->height;
}
public function getFormat() {
return $this->format;
}
public function getQuality() {
return $this->quality;
}
public function queryString() {
$head = "imageView2";
$res = "";
if($this->mode) {
$res .= $this->mode;
}
if($this->width) {
$res .= $this->width;
}
if($this->height) {
$res .= $this->height;
}
if($this->format) {
$res .= $this->format;
}
if($this->quality) {
$res .= $this->quality;
}
if($this->ignoreError) {
$res .= $this->ignoreError;
}
if($res) {
$res = $head . $res;
}
return $res;
}
public function resetRule() {
$this->mode = "";
$this->width = "";
$this->height = "";
$this->format = "";
$this->quality = "";
}
}

View File

@ -0,0 +1,212 @@
<?php
namespace Qcloud\Cos\ImageParamTemplate;
class ImageWatermarkTemplate extends ImageTemplate
{
private $image;
private $gravity;
private $dx;
private $dy;
private $blogo;
private $scatype;
private $spcent;
private $dissolve;
private $batch;
private $degree;
public function __construct() {
parent::__construct();
$this->image = "";
$this->gravity = "";
$this->dx = "";
$this->dy = "";
$this->blogo = "";
$this->scatype = "";
$this->spcent = "";
$this->dissolve = "";
$this->batch = "";
$this->degree = "";
}
/**
* 水印图片地址,需要经过 URL 安全的 Base64 编码。
* @param $value
*/
public function setImage($value) {
$this->image = "/image/" . $this->ciBase64($value);
}
/**
* 图片水印位置,九宫格位置(参考九宫格方位图 ),默认值 SouthEast
* @param $value
*/
public function setGravity($value) {
$this->gravity = "/gravity/" . $value;
}
/**
* 水平横轴边距单位为像素缺省值为0
* @param $value
*/
public function setDx($value) {
$this->dx = "/dx/" . $value;
}
/**
* 垂直纵轴边距单位为像素默认值为0
* @param $value
*/
public function setDy($value) {
$this->dy = "/dy/" . $value;
}
/**
* 水印图适配功能,适用于水印图尺寸过大的场景(如水印墙)。共有两种类型:
* 当 blogo 设置为1时水印图会被缩放至与原图相似大小后添加
* 当 blogo 设置为2时水印图会被直接裁剪至与原图相似大小后添加
* @param $value
*/
public function setBlogo($value) {
$this->blogo = "/blogo/" . $value;
}
/**
* 根据原图的大小,缩放调整水印图的大小:
* 当 scatype 设置为1时按原图的宽缩放
* 当 scatype 设置为2时按原图的高缩放
* 当 scatype 设置为3时按原图的整体面积缩放
* @param $value
*/
public function setScatype($value) {
$this->scatype = "/scatype/" . $value;
}
/**
* 与 scatype 搭配使用:
* 当 scatype 设置为1时该有效值为[1,1000],单位为千分比
* 当 scatype 设置为2时该有效值为[1,1000],单位为千分比
* 当 scatype 设置为3时该有效值为[1,250],单位为千分比。
* @param $value
*/
public function setSpcent($value) {
$this->spcent = "/spcent/" . $value;
}
/**
* 图片水印的透明度取值为1 - 100默认9090%不透明度)
* @param $value
*/
public function setDissolve($value) {
$this->dissolve = "/dissolve/" . $value;
}
/**
* 平铺水印功能可将图片水印平铺至整张图片。值为1时表示开启平铺水印功能
* @param $value
*/
public function setBatch($value) {
$this->batch = "/batch/" . $value;
}
/**
* 当 batch 值为1时生效。图片水印的旋转角度设置取值范围为0 - 360默认0
* @param $value
*/
public function setDegree($value) {
$this->degree = "/degree/" . $value;
}
public function getImage() {
return $this->image;
}
public function getGravity() {
return $this->gravity;
}
public function getDx() {
return $this->dx;
}
public function getDy() {
return $this->dy;
}
public function getBlogo() {
return $this->blogo;
}
public function getScatype() {
return $this->scatype;
}
public function getSpcent() {
return $this->spcent;
}
public function getDissolve() {
return $this->dissolve;
}
public function getBatch() {
return $this->batch;
}
public function getDegree() {
return $this->degree;
}
public function queryString() {
$head = "watermark/1";
$res = "";
if($this->image) {
$res .= $this->image;
}
if($this->gravity) {
$res .= $this->gravity;
}
if($this->dx) {
$res .= $this->dx;
}
if($this->dy) {
$res .= $this->dy;
}
if($this->blogo) {
$res .= $this->blogo;
}
if($this->scatype) {
$res .= $this->scatype;
}
if($this->spcent) {
$res .= $this->spcent;
}
if($this->dissolve) {
$res .= $this->dissolve;
}
if($this->batch) {
$res .= $this->batch;
}
if($this->degree) {
$res .= $this->degree;
}
if($res) {
$res = $head . $res;
}
return $res;
}
public function resetRule() {
$this->image = "";
$this->gravity = "";
$this->dx = "";
$this->dy = "";
$this->blogo = "";
$this->scatype = "";
$this->spcent = "";
$this->dissolve = "";
$this->batch = "";
$this->degree = "";
}
}

View File

@ -0,0 +1,64 @@
<?php
namespace Qcloud\Cos\ImageParamTemplate;
/**
* Class PicOperationsTransformation 图片处理参数 Pic-Operations
* @package Qcloud\Cos\ImageParamTemplate
*/
class PicOperationsTransformation {
private $isPicInfo;
private $rules;
public function __construct() {
$this->isPicInfo = 0;
$this->rules = array();
}
public function setIsPicInfo($value) {
$this->isPicInfo = $value;
}
public function addRule(ImageTemplate $template, $fileid = "", $bucket = "") {
$rule = $template->queryString();
if($rule){
$item = array();
$item['rule'] = $rule;
if($fileid){
$item['fileid'] = $fileid;
}
if($bucket) {
$item['bucket'] = $bucket;
}
$this->rules[] = $item;
}
}
public function getIsPicInfo() {
return $this->isPicInfo;
}
public function getRules() {
return $this->rules;
}
public function queryString() {
$res = "";
$picOperations = array();
if($this->isPicInfo){
$picOperations['is_pic_info'] = $this->isPicInfo;
}
if($this->rules){
$picOperations['rules'] = $this->rules;
}
if($picOperations){
$res = json_encode($picOperations);
}
return $res;
}
public function resetRule() {
$this->isPicInfo = 0;
$this->rules = array();
}
}

View File

@ -0,0 +1,208 @@
<?php
namespace Qcloud\Cos\ImageParamTemplate;
/**
* Parses default XML exception responses
*/
class TextWatermarkTemplate extends ImageTemplate
{
private $text;
private $font;
private $fontsize;
private $fill;
private $dissolve;
private $gravity;
private $dx;
private $dy;
private $batch;
private $degree;
private $shadow;
private $scatype;
private $spcent;
public function __construct() {
parent::__construct();
$this->text = "";
$this->font = "";
$this->fontsize = "";
$this->fill = "";
$this->dissolve = "";
$this->gravity = "";
$this->dx = "";
$this->dy = "";
$this->batch = "";
$this->degree = "";
$this->shadow = "";
$this->scatype = "";
$this->spcent = "";
}
public function setText($value) {
$this->text = "/text/" . $this->ciBase64($value);
}
public function setFont($value) {
$this->font = "/font/" . $this->ciBase64($value);
}
public function setFontsize($value) {
$this->fontsize = "/fontsize/" . $value;
}
public function setFill($value) {
$this->fill = "/fill/" . $this->ciBase64($value);
}
public function setDissolve($value) {
$this->dissolve = "/dissolve/" . $value;
}
public function setGravity($value) {
$this->gravity = "/gravity/" . $value;
}
public function setDx($value) {
$this->dx = "/dx/" . $value;
}
public function setDy($value) {
$this->dy = "/dy/" . $value;
}
public function setBatch($value) {
$this->batch = "/batch/" . $value;
}
public function setDegree($value) {
$this->degree = "/degree/" . $value;
}
public function setShadow($value) {
$this->shadow = "/shadow/" . $value;
}
public function setScatype($value) {
$this->scatype = "/scatype/" . $value;
}
public function setSpcent($value) {
$this->spcent = "/spcent/" . $value;
}
public function getText() {
return $this->text;
}
public function getFont() {
return $this->font;
}
public function getFontsize() {
return $this->fontsize;
}
public function getFill() {
return $this->fill;
}
public function getDissolve() {
return $this->dissolve;
}
public function getGravity() {
return $this->gravity;
}
public function getDx() {
return $this->dx;
}
public function getDy() {
return $this->dy;
}
public function getBatch() {
return $this->batch;
}
public function getDegree() {
return $this->degree;
}
public function getShadow() {
return $this->shadow;
}
public function getScatype() {
return $this->scatype;
}
public function getSpcent() {
return $this->spcent;
}
public function queryString() {
$head = "watermark/2";
$res = "";
if($this->text) {
$res .= $this->text;
}
if($this->font) {
$res .= $this->font;
}
if($this->fontsize) {
$res .= $this->fontsize;
}
if($this->fill) {
$res .= $this->fill;
}
if($this->dissolve) {
$res .= $this->dissolve;
}
if($this->gravity) {
$res .= $this->gravity;
}
if($this->dx) {
$res .= $this->dx;
}
if($this->dy) {
$res .= $this->dy;
}
if($this->batch) {
$res .= $this->batch;
}
if($this->degree) {
$res .= $this->degree;
}
if($this->shadow) {
$res .= $this->shadow;
}
if($this->scatype) {
$res .= $this->scatype;
}
if($this->spcent) {
$res .= $this->spcent;
}
if($res) {
$res = $head . $res;
}
return $res;
}
public function resetRule() {
$this->text = "";
$this->font = "";
$this->fontsize = "";
$this->fill = "";
$this->dissolve = "";
$this->gravity = "";
$this->dx = "";
$this->dy = "";
$this->batch = "";
$this->degree = "";
$this->shadow = "";
$this->scatype = "";
$this->spcent = "";
}
}

View File

@ -0,0 +1,167 @@
<?php
namespace Qcloud\Cos;
use GuzzleHttp\Pool;
class MultipartUpload {
const MIN_PART_SIZE = 1048576;
const MAX_PART_SIZE = 5368709120;
const DEFAULT_PART_SIZE = 5242880;
const MAX_PARTS = 10000;
private $client;
private $options;
private $partSize;
private $parts;
private $body;
private $progress;
private $totalSize;
private $uploadedSize;
public function __construct($client, $body, $options = array()) {
$minPartSize = $options['PartSize'];
unset($options['PartSize']);
$this->body = $body;
$this->client = $client;
$this->options = $options;
$this->partSize = $this->calculatePartSize($minPartSize);
$this->concurrency = isset($options['Concurrency']) ? $options['Concurrency'] : 10;
$this->progress = isset($options['Progress']) ? $options['Progress'] : function($totalSize, $uploadedSize) {};
$this->parts = [];
$this->partNumberList = [];
$this->uploadedSize = 0;
$this->totalSize = $this->body->getSize();
$this->needMd5 = isset($options['ContentMD5']) ? $options['ContentMD5'] : true;
$this->retry = isset($options['Retry']) ? $options['Retry'] : 3;
}
public function performUploading() {
$uploadId= $this->initiateMultipartUpload();
$this->uploadParts($uploadId);
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) {
$uploadRequests = function ($uploadId) {
$partNumber = 1;
$index = 1;
$offset = 0;
$partSize = 0;
for ( ; ; $partNumber ++) {
if ($this->body->eof()) {
break;
}
$body = $this->body->read($this->partSize);
$partSize = $this->partSize;
if ($offset + $this->partSize >= $this->totalSize) {
$partSize = $this->totalSize - $offset;
}
$offset += $partSize;
if (empty($body)) {
break;
}
if (isset($this->parts[$partNumber])) {
continue;
}
$this->partNumberList[$index]['PartNumber'] = $partNumber;
$this->partNumberList[$index]['PartSize'] = $partSize;
$params = array(
'Bucket' => $this->options['Bucket'],
'Key' => $this->options['Key'],
'UploadId' => $uploadId,
'PartNumber' => $partNumber,
'Body' => $body,
'ContentMD5' => $this->needMd5
);
if ($this->needMd5 == false) {
unset($params["ContentMD5"]);
}
if (!isset($this->parts[$partNumber])) {
$command = $this->client->getCommand('uploadPart', $params);
$request = $this->client->commandToRequestTransformer($command);
$index ++;
yield $request;
}
}
};
$pool = new Pool($this->client->httpClient, $uploadRequests($uploadId), [
'concurrency' => $this->concurrency,
'fulfilled' => function ($response, $index) {
$index = $index + 1;
$partNumber = $this->partNumberList[$index]['PartNumber'];
$partSize = $this->partNumberList[$index]['PartSize'];
//兼容两种写法防止index为undefined
if (array_key_exists('etag', $response->getHeaders())) {
$etag = $response->getHeaders()["etag"][0];
}
if (array_key_exists('ETag', $response->getHeaders())) {
$etag = $response->getHeaders()["ETag"][0];
}
$part = array('PartNumber' => $partNumber, 'ETag' => $etag);
$this->parts[$partNumber] = $part;
$this->uploadedSize += $partSize;
call_user_func_array($this->progress, [$this->totalSize, $this->uploadedSize]);
},
'rejected' => function ($reason, $index) {
printf("part [%d] upload failed, reason: %s\n", $index, $reason);
throw($reason);
}
]);
$promise = $pool->promise();
$promise->wait();
}
public function resumeUploading() {
$uploadId = $this->options['UploadId'];
$rt = $this->client->ListParts(
array('UploadId' => $uploadId,
'Bucket'=>$this->options['Bucket'],
'Key'=>$this->options['Key']));
$parts = array();
if (count($rt['Parts']) > 0) {
foreach ($rt['Parts'] as $part) {
$this->parts[$part['PartNumber']] = array('PartNumber' => $part['PartNumber'], 'ETag' => $part['ETag']);
}
}
$this->uploadParts($uploadId);
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)
);
}
private function calculatePartSize($minPartSize)
{
$partSize = intval(ceil(($this->body->getSize() / 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'];
}
}

View File

@ -0,0 +1,145 @@
<?php
namespace Qcloud\Cos;
use GuzzleHttp\Pool;
class RangeDownload {
const DEFAULT_PART_SIZE = 52428800;
private $client;
private $options;
private $partSize;
private $parts;
private $progress;
private $totalSize;
private $resumableJson;
public function __construct( $client, $contentLength, $saveAs, $options = array() ) {
$this->client = $client;
$this->options = $options;
$this->partSize = isset( $options['PartSize'] ) ? $options['PartSize'] : self::DEFAULT_PART_SIZE;
$this->concurrency = isset( $options['Concurrency'] ) ? $options['Concurrency'] : 10;
$this->progress = isset( $options['Progress'] ) ? $options['Progress'] : function( $totalSize, $downloadedSize ) {
}
;
$this->parts = [];
$this->partNumberList = [];
$this->downloadedSize = 0;
$this->totalSize = $contentLength;
$this->saveAs = $saveAs;
$this->resumableJson = [];
$this->resumableJson = isset( $options['ResumableJson'] ) ? $options['ResumableJson'] : [];
unset( $options['ResumableJson'] );
$this->resumableTaskFile = isset( $options['ResumableTaskFile'] ) ? $options['ResumableTaskFile'] : $saveAs . '.cosresumabletask';
$this->resumableDownload = isset( $options['ResumableDownload'] ) ? $options['ResumableDownload'] : false;
}
public function performdownloading() {
if ( $this->resumableDownload ) {
try {
if ( file_exists( $this->resumableTaskFile ) ) {
$origin_content = file_get_contents( $this->resumableTaskFile );
$this->resumableJsonLocal = json_decode( $origin_content, true );
if ( $this->resumableJsonLocal == null ) {
$this->resumableJsonLocal = [];
} else if ( $this->resumableJsonLocal['LastModified'] != $this->resumableJson['LastModified'] ||
$this->resumableJsonLocal['ContentLength'] != $this->resumableJson['ContentLength'] ||
$this->resumableJsonLocal['ETag'] != $this->resumableJson['ETag'] ||
$this->resumableJsonLocal['Crc64ecma'] != $this->resumableJson['Crc64ecma'] ) {
$this->resumableDownload = false;
}
}
} catch ( \Exception $e ) {
$this->resumableDownload = false;
}
}
try {
if ($this->resumableDownload) {
$this->fp = fopen( $this->saveAs, 'r+' );
} else {
$this->fp = fopen( $this->saveAs, 'wb' );
}
$rt = $this->donwloadParts();
$this->resumableJson['DownloadedBlocks'] = [];
if (file_exists( $this->resumableTaskFile )) {
unlink($this->resumableTaskFile);
}
} catch ( \Exception $e ) {
$this->fp_resume = fopen( $this->resumableTaskFile, 'wb' );
fwrite( $this->fp_resume, json_encode( $this->resumableJson ) );
fclose( $this->fp_resume );
throw ( $e );
}
finally {
fclose( $this->fp );
}
return $rt;
}
public function donwloadParts() {
$uploadRequests = function () {
$index = 1;
$partSize = 0;
for ( $offset = 0; $offset < $this->totalSize; ) {
$partSize = $this->partSize;
if ( $offset + $this->partSize >= $this->totalSize ) {
$partSize = $this->totalSize - $offset;
}
$this->parts[$index]['PartSize'] = $partSize;
$this->parts[$index]['Offset'] = $offset;
$begin = $offset;
$end = $offset + $partSize - 1;
if ( !( $this->resumableDownload &&
isset( $this->resumableJsonLocal['DownloadedBlocks'] ) &&
in_array( ['from' => $begin, 'to' => $end], $this->resumableJsonLocal['DownloadedBlocks'] ) ) ) {
$params = array(
'Bucket' => $this->options['Bucket'],
'Key' => $this->options['Key'],
'Range' => sprintf( 'bytes=%d-%d', $begin, $end )
);
$command = $this->client->getCommand( 'getObject', $params );
$request = $this->client->commandToRequestTransformer( $command );
$index += 1;
yield $request;
} else {
$this->resumableJson['DownloadedBlocks'][] = ['from' => $begin, 'to' => $end];
$this->downloadedSize += $partSize;
call_user_func_array( $this->progress, [$this->totalSize, $this->downloadedSize] );
}
$offset += $partSize;
}
}
;
$pool = new Pool( $this->client->httpClient, $uploadRequests(), [
'concurrency' => $this->concurrency,
'fulfilled' => function ( $response, $index ) {
$index = $index + 1;
$stream = $response->getBody();
$offset = $this->parts[$index]['Offset'];
$partsize = 8192;
$begin = $offset;
fseek( $this->fp, $offset );
while ( !$stream->eof() ) {
$output = $stream->read( $partsize );
$writeLen = fwrite( $this->fp, $output );
$offset += $writeLen;
}
$end = $offset - 1;
$this->resumableJson['DownloadedBlocks'][] = ['from' => $begin, 'to' => $end];
$partSize = $this->parts[$index]['PartSize'];
$this->downloadedSize += $partSize;
call_user_func_array( $this->progress, [$this->totalSize, $this->downloadedSize] );
}
,
'rejected' => function ( $reason, $index ) {
throw( $reason );
}
] );
$promise = $pool->promise();
$promise->wait();
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace Qcloud\Cos\Request;
use GuzzleHttp\Command\Guzzle\RequestLocation\AbstractLocation;
use GuzzleHttp\Command\CommandInterface;
use GuzzleHttp\Command\Guzzle\Parameter;
use GuzzleHttp\Psr7;
use Psr\Http\Message\MessageInterface;
use Psr\Http\Message\RequestInterface;
/**
* Adds a raw/binary body to a request.
* This is here because: https://github.com/guzzle/guzzle-services/issues/160
*/
class BodyLocation extends AbstractLocation
{
/**
* Set the name of the location
*
* @param string $locationName
*/
public function __construct($locationName = 'body')
{
parent::__construct($locationName);
}
/**
* @param CommandInterface $command
* @param RequestInterface $request
* @param Parameter $param
*
* @return MessageInterface
*/
public function visit(
CommandInterface $command,
RequestInterface $request,
Parameter $param
) {
$value = $request->getBody()->getContents();
if ('' !== $value) {
throw new \RuntimeException('Only one "body" location may exist per operation');
}
// binary string data from bound parameter
$value = $command[$param->getName()];
return $request->withBody(Psr7\Utils::streamFor($value));
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace Qcloud\Cos\Request;
use GuzzleHttp\Command\Guzzle\RequestLocation\XmlLocation as DefaultXmlLocation;
class XmlLocation extends DefaultXmlLocation
{
protected function writeElement(\XMLWriter $writer, $prefix, $name, $namespace, $value)
{
if ($namespace) {
$writer->startElementNS($prefix, $name, $namespace);
} else {
$writer->startElement($name);
}
// Remove use writeCdata
$writer->writeRaw($value);
$writer->endElement();
}
}

View File

@ -0,0 +1,263 @@
<?php
namespace Qcloud\Cos;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\Command\CommandInterface;
use GuzzleHttp\Command\Result;
class ResultTransformer {
private $config;
private $operation;
public function __construct($config, $operation) {
$this->config = $config;
$this->operation = $operation;
}
public function writeDataToLocal(CommandInterface $command, RequestInterface $request, ResponseInterface $response) {
$action = $command->getName();
if ($action == "GetObject" || $action == "GetSnapshot" || $action == "ImageRepairProcess") {
if (isset($command['SaveAs'])) {
$fp = fopen($command['SaveAs'], "wb");
$stream = $response->getBody();
$offset = 0;
$partsize = 8192;
while (!$stream->eof()) {
$output = $stream->read($partsize);
fseek($fp, $offset);
fwrite($fp, $output);
$offset += $partsize;
}
fclose($fp);
}
}
}
public function metaDataTransformer(CommandInterface $command, ResponseInterface $response, Result $result) {
$headers = $response->getHeaders();
$metadata = array();
foreach ($headers as $key => $value) {
if (strpos($key, "x-cos-meta-") === 0) {
$metadata[substr($key, 11)] = $value[0];
}
}
if (!empty($metadata)) {
$result['Metadata'] = $metadata;
}
return $result;
}
public function extraHeadersTransformer(CommandInterface $command, RequestInterface $request, Result $result) {
if ($command['Key'] != null && $result['Key'] == null) {
$result['Key'] = $command['Key'];
}
if ($command['Bucket'] != null && $result['Bucket'] == null) {
$result['Bucket'] = $command['Bucket'];
}
$result['Location'] = $request->getHeader('Host')[0] . $request->getUri()->getPath();
if ($this->config['locationWithSchema']) {
$result['Location'] = $this->config['schema'] . '://' . $result['Location'];
}
return $result;
}
public function selectContentTransformer(CommandInterface $command, Result $result) {
$action = $command->getName();
if ($action == "SelectObjectContent") {
$result['Data'] = $this->getSelectContents($result);
}
return $result;
}
public function ciContentInfoTransformer(CommandInterface $command, Result $result) {
$action = $command->getName();
if ($action == "ImageInfo" || $action == "ImageExif" || $action == "ImageAve" || $action == "GetPrivateM3U8") {
$length = intval($result['ContentLength']);
if($length > 0){
$result['Data'] = $this->geCiContentInfo($result, $length);
}
}
if ($action == "PutObject" && isset($command["PicOperations"]) && $command["PicOperations"]) {
$picOperations = json_decode($command["PicOperations"], true);
$picRuleSize = isset($picOperations['rules']) && is_array($picOperations['rules']) ? sizeof($picOperations['rules']) : 0;
$length = intval($result['ContentLength']);
if($length > 0){
$content = $this->geCiContentInfo($result, $length);
$obj = simplexml_load_string($content, "SimpleXMLElement", LIBXML_NOCDATA);
$xmlData = json_decode(json_encode($obj),true);
if ($picRuleSize == 1 && isset($xmlData['ProcessResults']['Object'])){
$tmp = $xmlData['ProcessResults']['Object'];
unset($xmlData['ProcessResults']['Object']);
$xmlData['ProcessResults']['Object'][] = $tmp;
}
$result['Data'] = $xmlData;
}
}
if ($action == "GetBucketGuetzli") {
$length = intval($result['ContentLength']);
if($length > 0){
$content = $this->geCiContentInfo($result, $length);
$obj = simplexml_load_string($content, "SimpleXMLElement", LIBXML_NOCDATA);
$arr = json_decode(json_encode($obj),true);
$result['GuetzliStatus'] = isset($arr[0]) ? $arr[0] : '';
}
}
if ($action == "GetCiService") {
$length = intval($result['ContentLength']);
if($length > 0){
$content = $this->geCiContentInfo($result, $length);
$obj = simplexml_load_string($content, "SimpleXMLElement", LIBXML_NOCDATA);
$arr = json_decode(json_encode($obj),true);
$result['CIStatus'] = isset($arr[0]) ? $arr[0] : '';
unset($result['Body']);
}
}
if ($action == "GetOriginProtect") {
$length = intval($result['ContentLength']);
if($length > 0){
$content = $this->geCiContentInfo($result, $length);
$obj = simplexml_load_string($content, "SimpleXMLElement", LIBXML_NOCDATA);
$arr = json_decode(json_encode($obj),true);
$result['OriginProtectStatus'] = isset($arr[0]) ? $arr[0] : '';
unset($result['Body']);
}
}
if ($action == "GetHotLink") {
$length = intval($result['ContentLength']);
if($length > 0){
$content = $this->geCiContentInfo($result, $length);
$obj = simplexml_load_string($content, "SimpleXMLElement", LIBXML_NOCDATA);
$arr = json_decode(json_encode($obj),true);
$result['Hotlink'] = $arr;
unset($result['Body']);
}
}
$xml2JsonActions = array(
'CreateMediaTranscodeJobs' => 1,
'CreateMediaJobs' => 1,
'DescribeMediaJob' => 1,
'DescribeMediaJobs' => 1,
'CreateMediaSnapshotJobs' => 1,
'CreateMediaConcatJobs' => 1,
'CreateMediaVoiceSeparateJobs' => 1,
'DescribeMediaVoiceSeparateJob' => 1,
'UpdateMediaQueue' => 1,
'CreateMediaSmartCoverJobs' => 1,
'CreateMediaVideoProcessJobs' => 1,
'CreateMediaVideoMontageJobs' => 1,
'CreateMediaAnimationJobs' => 1,
'CreateMediaPicProcessJobs' => 1,
'CreateMediaSegmentJobs' => 1,
'CreateMediaVideoTagJobs' => 1,
'CreateMediaSuperResolutionJobs' => 1,
'CreateMediaSDRtoHDRJobs' => 1,
'CreateMediaDigitalWatermarkJobs' => 1,
'CreateMediaExtractDigitalWatermarkJobs' => 1,
'OpticalOcrRecognition' => 1,
'GetWorkflowInstance' => 1,
'CreateMediaTranscodeTemplate' => 1,
'UpdateMediaTranscodeTemplate' => 1,
'CreateMediaHighSpeedHdTemplate' => 1,
'UpdateMediaHighSpeedHdTemplate' => 1,
'CreateMediaAnimationTemplate' => 1,
'UpdateMediaAnimationTemplate' => 1,
'CreateMediaConcatTemplate' => 1,
'UpdateMediaConcatTemplate' => 1,
'CreateMediaVideoProcessTemplate' => 1,
'UpdateMediaVideoProcessTemplate' => 1,
'CreateMediaVideoMontageTemplate' => 1,
'UpdateMediaVideoMontageTemplate' => 1,
'CreateMediaVoiceSeparateTemplate' => 1,
'UpdateMediaVoiceSeparateTemplate' => 1,
'CreateMediaSuperResolutionTemplate' => 1,
'UpdateMediaSuperResolutionTemplate' => 1,
'CreateMediaPicProcessTemplate' => 1,
'UpdateMediaPicProcessTemplate' => 1,
'CreateMediaWatermarkTemplate' => 1,
'UpdateMediaWatermarkTemplate' => 1,
'CreateInventoryTriggerJob' => 1,
'DescribeInventoryTriggerJobs' => 1,
'DescribeInventoryTriggerJob' => 1,
'CreateMediaNoiseReductionJobs' => 1,
'CreateMediaQualityEstimateJobs' => 1,
'CreateMediaStreamExtractJobs' => 1,
);
if (key_exists($action, $xml2JsonActions)) {
$length = intval($result['ContentLength']);
if($length > 0){
$content = $this->geCiContentInfo($result, $length);
$obj = simplexml_load_string($content, "SimpleXMLElement", LIBXML_NOCDATA);
$xmlData = json_decode(json_encode($obj),true);
$result['Response'] = $xmlData;
}
}
return $result;
}
public function geCiContentInfo($result, $length) {
$f = $result['Body'];
$data = "";
while (!$f->eof()) {
$tmp = $f->read($length);
if (empty($tmp)) {
break;
}
$data .= $tmp;
}
return $data;
}
public function getSelectContents($result) {
$f = $result['RawData'];
while (!$f->eof()) {
$data = array();
$tmp = $f->read(4);
if (empty($tmp)) {
break;
}
$total_length = (int)(unpack("N", $tmp)[1]);
$headers_length = (int)(unpack("N", $f->read(4))[1]);
$body_length = $total_length - $headers_length - 16;
$predule_crc = (int)(unpack("N", $f->read(4))[1]);
$headers = array();
for ($offset = 0; $offset < $headers_length;) {
$key_length = (int)(unpack("C", $f->read(1))[1]);
$key = $f->read($key_length);
$head_value_type = (int)(unpack("C", $f->read(1))[1]);
$value_length = (int)(unpack("n", $f->read(2))[1]);
$value = $f->read($value_length);
$offset += 4 + $key_length + $value_length;
if ($key == ":message-type") {
$data['MessageType'] = $value;
}
if ($key == ":event-type") {
$data['EventType'] = $value;
}
if ($key == ":error-code") {
$data['ErrorCode'] = $value;
}
if ($key == ":error-message") {
$data['ErrorMessage'] = $value;
}
}
$body = $f->read($body_length);
$message_crc = (int)(unpack("N", $f->read(4))[1]);
$data['Body'] = $body;
yield $data;
}
}
public function __destruct() {
}
}

View File

@ -0,0 +1,82 @@
<?php
namespace Qcloud\Cos;
use GuzzleHttp\Command\CommandInterface;
use GuzzleHttp\Command\Guzzle\DescriptionInterface;
use GuzzleHttp\Command\Guzzle\Serializer as DefaultSerializer;
use Psr\Http\Message\RequestInterface;
/**
* Override Request serializer to modify authentication mechanism
*/
class Serializer extends DefaultSerializer
{
/**
* {@inheritdoc}
*/
public function __construct(
DescriptionInterface $description,
array $requestLocations = []
) {
// Override Guzzle's body location as it isn't raw binary data
$requestLocations['body'] = new Request\BodyLocation();
$requestLocations['xml'] = new Request\XmlLocation();
parent::__construct($description, $requestLocations);
}
/**
* Authorization header is Loco's preferred authorization method.
* Add Authorization header to request if API key is set, unless query is explicitly configured as auth method.
* Unset key from command to avoid sending it as a query param.
*
* @override
*
* @param CommandInterface $command
* @param RequestInterface $request
*
* @return RequestInterface
*
* @throws \InvalidArgumentException
*/
protected function prepareRequest(
CommandInterface $command,
RequestInterface $request
) {
/*
if ($command->offsetExists('key') === true) {
$mode = empty($command->offsetGet('auth')) === false
? $command->offsetGet('auth')
: 'loco';
if ($mode !== 'query') {
// else use Authorization header of various types
if ($mode === 'loco') {
$value = 'Loco '.$command->offsetGet('key');
$request = $request->withHeader('Authorization', $value);
} elseif ($mode === 'basic') {
$value = 'Basic '.base64_encode($command->offsetGet('key').':');
$request = $request->withHeader('Authorization', $value);
} else {
throw new \InvalidArgumentException("Invalid auth type: {$mode}");
}
// avoid request sending key parameter in query string
$command->offsetUnset('key');
}
}
// Remap legacy parameters to common `data` binding on request body
static $remap = [
'import' => ['src'=>'data'],
'translate' => ['translation'=>'data'],
];
$name = $command->getName();
if (isset($remap[$name])) {
foreach ($remap[$name] as $old => $new) {
if ($command->offsetExists($old)) {
$command->offsetSet($new, $command->offsetGet($old));
$command->offsetUnset($old);
}
}
}
*/
return parent::prepareRequest($command, $request);
}
}

7479
vendor/qcloud/cos-sdk-v5/src/Service.php vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,130 @@
<?php
namespace Qcloud\Cos;
use Psr\Http\Message\RequestInterface;
class Signature {
// string: access key.
private $accessKey;
// string: secret key.
private $secretKey;
// array: cos config.
private $options;
// string: token.
private $token;
// array: sign header.
private $signHeader;
public function __construct( $accessKey, $secretKey, $options, $token = null ) {
$this->accessKey = $accessKey;
$this->secretKey = $secretKey;
$this->options = $options;
$this->token = $token;
$this->signHeader = [
'cache-control',
'content-disposition',
'content-encoding',
'content-length',
'content-md5',
'content-type',
'expect',
'expires',
'host',
'if-match',
'if-modified-since',
'if-none-match',
'if-unmodified-since',
'origin',
'range',
'transfer-encoding',
];
date_default_timezone_set($this->options['timezone']);
}
public function __destruct() {
}
public function needCheckHeader( $header ) {
if ( startWith( $header, 'x-cos-' ) ) {
return true;
}
if ( in_array( $header, $this->signHeader ) ) {
return true;
}
return false;
}
public function signRequest( RequestInterface $request ) {
$authorization = $this->createAuthorization( $request );
return $request->withHeader( 'Authorization', $authorization );
}
public function createAuthorization( RequestInterface $request, $expires = '+30 minutes' ) {
if ( is_null( $expires ) || !strtotime( $expires )) {
$expires = '+30 minutes';
}
$signTime = ( string )( time() - 60 ) . ';' . ( string )( strtotime( $expires ) );
$urlParamListArray = [];
foreach ( explode( '&', $request->getUri()->getQuery() ) as $query ) {
if (!empty($query)) {
$tmpquery = explode( '=', $query );
//为了保证CI的key中有=号的情况也能正常通过ci在这层之前已经encode了这里需要拆开重新encode防止上方explode拆错
$key = strtolower( rawurlencode(urldecode($tmpquery[0])) );
if (count($tmpquery) >= 2) {
$value = $tmpquery[1];
} else {
$value = "";
}
//host开关
if (!$this->options['signHost'] && $key == 'host') {
continue;
}
$urlParamListArray[$key] = $key. '='. $value;
}
}
ksort($urlParamListArray);
$urlParamList = join(';', array_keys($urlParamListArray));
$httpParameters = join('&', array_values($urlParamListArray));
$headerListArray = [];
foreach ( $request->getHeaders() as $key => $value ) {
$key = strtolower( urlencode( $key ) );
$value = rawurlencode( $value[0] );
if ( !$this->options['signHost'] && $key == 'host' ) {
continue;
}
if ( $this->needCheckHeader( $key ) ) {
$headerListArray[$key] = $key. '='. $value;
}
}
ksort($headerListArray);
$headerList = join(';', array_keys($headerListArray));
$httpHeaders = join('&', array_values($headerListArray));
$httpString = strtolower( $request->getMethod() ) . "\n" . urldecode( $request->getUri()->getPath() ) . "\n" . $httpParameters.
"\n". $httpHeaders. "\n";
$sha1edHttpString = sha1( $httpString );
$stringToSign = "sha1\n$signTime\n$sha1edHttpString\n";
$signKey = hash_hmac( 'sha1', $signTime, trim($this->secretKey) );
$signature = hash_hmac( 'sha1', $stringToSign, $signKey );
$authorization = 'q-sign-algorithm=sha1&q-ak='. trim($this->accessKey) .
"&q-sign-time=$signTime&q-key-time=$signTime&q-header-list=$headerList&q-url-param-list=$urlParamList&" .
"q-signature=$signature";
return $authorization;
}
public function createPresignedUrl( RequestInterface $request, $expires = '+30 minutes' ) {
$authorization = $this->createAuthorization( $request, $expires);
$uri = $request->getUri();
$query = 'sign='.urlencode( $authorization ) . '&' . $uri->getQuery();
if ( $this->token != null ) {
$query = $query.'&x-cos-security-token='.$this->token;
}
$uri = $uri->withQuery( $query );
return $uri;
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace Qcloud\Cos;
use Psr\Http\Message\RequestInterface;
class SignatureMiddleware {
private $nextHandler;
protected $signature;
/**
* @param callable $nextHandler Next handler to invoke.
*/
public function __construct(callable $nextHandler, $accessKey, $secretKey, $options) {
$this->nextHandler = $nextHandler;
$this->signature = new Signature($accessKey, $secretKey, $options);
}
public function __invoke(RequestInterface $request, array $options) {
$fn = $this->nextHandler;
return $fn($this->signature->signRequest($request), $options);
}
}