123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576 |
- <?php
- /**
- * +----------------------------------------------------------------------
- * | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
- * +----------------------------------------------------------------------
- * | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved.
- * +----------------------------------------------------------------------
- * | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
- * +----------------------------------------------------------------------
- * | Author: CRMEB Team <admin@crmeb.com>
- * +----------------------------------------------------------------------
- */
- namespace crmeb\services\upload\extend\cos;
- use crmeb\exceptions\UploadException;
- use crmeb\services\upload\XML;
- /**
- * Class Client
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2022/9/29
- * @package crmeb\services\upload\extend\cos
- */
- class Client
- {
- /**
- * @var string
- */
- protected $accessKey;
- /**
- * @var string
- */
- protected $secretKey;
- /**
- * @var string
- */
- protected $appid;
- /**
- * @var mixed|string
- */
- protected $bucket;
- /**
- * @var mixed|string
- */
- protected $region;
- /**
- * @var mixed|string
- */
- protected $uploadUrl;
- /**
- * @var string
- */
- protected $action = '';
- /**
- * @var array
- */
- protected $response = ['content' => null, 'code' => 200, 'header' => []];
- /**
- * @var array
- */
- protected $request = ['header' => [], 'body' => [], 'host' => ''];
- /**
- * @var string
- */
- protected $cosacl = 'public-read';
- /**
- * Client constructor.
- * @param array $config
- */
- public function __construct(array $config)
- {
- $this->accessKey = $config['accessKey'] ?? '';
- $this->secretKey = $config['secretKey'] ?? '';
- $this->appid = $config['appid'] ?? '';
- $this->bucket = $config['bucket'] ?? '';
- $this->region = $config['region'] ?? 'ap-chengdu';
- $this->uploadUrl = $config['uploadUrl'] ?? '';
- }
- /**
- * 获取实际请求
- * @return array
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2022/10/17
- */
- public function getResponse()
- {
- $response = $this->response;
- $this->response = ['content' => null, 'http_code' => 200, 'header' => []];
- return $response;
- }
- /**
- * @return array
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2022/10/17
- */
- public function getRequest()
- {
- $request = $this->request;
- $this->request = ['header' => [], 'body' => [], 'host' => ''];
- return $request;
- }
- /**
- * 拼接请求地址
- * @return string
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2022/9/29
- */
- protected function makeUpUrl()
- {
- return $this->bucket . '.cos.' . $this->region . '.myqcloud.com';
- }
- /**
- * @return bool
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2022/9/29
- */
- protected function ssl()
- {
- return strstr($this->uploadUrl, 'https://') !== false;
- }
- /**
- * 检查参数
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2022/9/29
- */
- protected function checkOptions()
- {
- if (!$this->bucket) {
- throw new UploadException('请传入桶名');
- }
- if (!$this->region) {
- throw new UploadException('请传入所属地域');
- }
- if (!$this->accessKey) {
- throw new UploadException('请传入SecretId');
- }
- if (!$this->secretKey) {
- throw new UploadException('请传入SecretKey');
- }
- }
- /**
- * 上传文件
- * @param string $key
- * @param $body
- * @return string[]
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2022/9/29
- */
- public function putObject(string $key, $body)
- {
- $this->checkOptions();
- $url = $this->makeUpUrl();
- $header = [
- 'Content-Type' => 'image/jpeg',
- 'x-cos-acl' => $this->cosacl,
- 'Content-MD5' => base64_encode(md5($body, true)),
- 'Host' => $url
- ];
- $imageUrl = ($this->ssl() ? 'https://' : 'http://') . $url . '/' . $key;
- $res = $this->request($imageUrl, 'PUT', ['body' => $body], $header);
- if ($res && !empty($res['Message'])) {
- throw new UploadException($res['Message']);
- }
- return [
- 'name' => $key,
- 'path' => $imageUrl
- ];
- }
- /**
- * 删除文件
- * @param string $bucket
- * @param string $key
- * @return array|false
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2022/10/19
- */
- public function deleteObject(string $bucket, string $key)
- {
- $url = $this->getRequestHost($bucket);
- $header = [
- 'Host' => $url
- ];
- $res = $this->request('https://' . $url . '/' . $key, 'delete', [], $header);
- if ($res && !empty($res['Message'])) {
- throw new UploadException($res['Message']);
- }
- return $res;
- }
- /**
- * 获取桶列表
- * @return array|false|\SimpleXMLElement|string
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2022/10/19
- */
- public function listBuckets()
- {
- $url = 'service.cos.myqcloud.com';
- $header = [
- 'Host' => $url
- ];
- $res = $this->request('https://' . $url . '/', 'get', [], $header);
- if ($res && !empty($res['Message'])) {
- throw new UploadException($res['Message']);
- }
- return $res;
- }
- /**
- * 检测桶,不存在返回true
- * @param string $bucket
- * @param string $region
- * @return bool
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2022/10/17
- */
- public function headBucket(string $bucket, string $region = '')
- {
- $url = $this->getRequestHost($bucket, $region);
- $header = [
- 'Host' => $url
- ];
- $this->request('https://' . $url, 'head', [], $header);
- $response = $this->getResponse();
- return $response['code'] == 404;
- }
- /**
- * 创建桶
- * @param string $bucket
- * @param string $region
- * @param string $acl
- * @return array|false|\SimpleXMLElement|string
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2022/10/17
- */
- public function createBucket(string $bucket, string $region = '', string $acl = 'public-read')
- {
- return $this->noBodyRequest('put', $bucket, $region, $acl);
- }
- /**
- * 组合成xml
- * @param array $data
- * @param string $root
- * @param string $itemKey
- * @return string
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2022/10/17
- */
- protected function xmlBuild(array $xmlAttr, string $root = 'xml', string $itemKey = 'item')
- {
- $xml = '<' . $root . '>';
- $xml .= '<' . $itemKey . '>';
- foreach ($xmlAttr as $kk => $vv) {
- if (is_array($vv)) {
- foreach ($vv as $v) {
- $xml .= '<' . $kk . '>' . $v . '</' . $kk . '>';
- }
- } else {
- $xml .= '<' . $kk . '>' . $vv . '</' . $kk . '>';
- }
- }
- $xml .= '</' . $itemKey . '>';
- $xml .= '</' . $root . '>';
- return $xml;
- }
- /**
- * 设置跨域
- * @param string $bucket
- * @param string $region
- * @param array $data
- * @return string
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2022/10/17
- */
- public function putBucketCors(string $bucket, array $data, string $region = '')
- {
- $url = $this->getRequestHost($bucket, $region);
- $xml = $this->xmlBuild($data, 'CORSConfiguration', 'CORSRule');
- $header = [
- 'Host' => $url,
- 'Content-Type' => 'application/xml',
- 'Content-Length' => strlen($xml),
- 'Content-MD5' => base64_encode(md5($xml, true))
- ];
- $res = $this->request('https://' . $url . '/?cors', 'put', ['xml' => $xml], $header);
- if ($res && !empty($res['Message'])) {
- throw new UploadException($res['Message']);
- }
- return $res;
- }
- /**
- * 删除
- * @param string $name
- * @param string $region
- * @return array|false|\SimpleXMLElement|string
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2022/10/17
- */
- public function deleteBucket(string $name, string $region = '')
- {
- return $this->noBodyRequest('delete', $name, $region);
- }
- /**
- * 获取桶下的
- * @param string $name
- * @param string $region
- * @return array|false|\SimpleXMLElement|string
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2022/10/17
- */
- public function getBucketDomain(string $name, string $region = '')
- {
- $this->action = 'domain';
- return $this->noBodyRequest('get', $name, $region);
- }
- /**
- * 绑定域名
- * @param string $bucket
- * @param string $region
- * @param array $data
- * @return array|false|\SimpleXMLElement|string
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2022/10/19
- */
- public function putBucketDomain(string $bucket, string $region, array $data)
- {
- $url = $this->getRequestHost($bucket, $region);
- $xml = $this->xmlBuild($data, 'DomainConfiguration', 'DomainRule');
- $header = [
- 'Host' => $url,
- 'Content-Type' => 'application/xml',
- 'Content-Length' => strlen($xml),
- 'Content-MD5' => base64_encode(md5($xml, true))
- ];
- $res = $this->request('https://' . $url . '/?domain', 'put', ['xml' => $xml], $header);
- if ($res && !empty($res['Message'])) {
- throw new UploadException($res['Message']);
- }
- return $res;
- }
- /**
- * @param string $bucket
- * @param string $region
- * @return string
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2022/10/17
- */
- protected function getRequestHost(string $bucket, string $region = '')
- {
- if (!$this->accessKey) {
- throw new UploadException('请传入SecretId');
- }
- if (!$this->secretKey) {
- throw new UploadException('请传入SecretKey');
- }
- if (strstr($bucket, '-') === false) {
- $bucket = $bucket . '-' . $this->appid;
- }
- return $bucket . '.cos.' . ($region ?: $this->region) . '.myqcloud.com';
- }
- /**
- * @param string $method
- * @param string $bucket
- * @param string $region
- * @param string|null $acl
- * @return array|false|\SimpleXMLElement|string
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2022/10/17
- */
- public function noBodyRequest(string $method, string $bucket, string $region = '', string $acl = null, bool $isExc = true)
- {
- $url = $this->getRequestHost($bucket, $region);
- $header = [
- 'Host' => $url
- ];
- if ($acl) {
- $header['x-cos-acl'] = $acl;
- }
- if (in_array($method, ['put', 'post'])) {
- $header['Content-Length'] = 0;
- }
- $res = $this->request('https://' . $url . '/' . ($this->action ? '?' . $this->action : ''), $method, [], $header);
- $this->action = '';
- if ($isExc) {
- if ($res && !empty($res['Message'])) {
- throw new UploadException($res['Message']);
- }
- }
- return $res;
- }
- /**
- * 发起请求
- * @param string $url
- * @param string $method
- * @param array $data
- * @param array $header
- * @param int $timeout
- * @return array|false|\SimpleXMLElement|string
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2022/9/29
- */
- public function request(string $url, string $method, array $data, array $header = [], int $timeout = 5)
- {
- $this->request['body'] = $data;
- $this->request['host'] = $url;
- $urlAttr = parse_url($url);
- $curl = curl_init($url);
- $method = strtoupper($method);
- //请求方式
- curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
- //超时时间
- curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
- //设置header头
- $header = array_merge($header, $this->getSign($url, $method, $urlAttr['path'] ?? '', [], $header));
- $this->request['header'] = $header;
- $clientHeader = [];
- foreach ($header as $key => $item) {
- $clientHeader[] = $key . ':' . $item;
- }
- curl_setopt($curl, CURLOPT_HTTPHEADER, $clientHeader);
- curl_setopt($curl, CURLOPT_FAILONERROR, false);
- //返回抓取数据
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
- //输出header头信息
- curl_setopt($curl, CURLOPT_HEADER, true);
- //TRUE 时追踪句柄的请求字符串,从 PHP 5.1.3 开始可用。这个很关键,就是允许你查看请求header
- curl_setopt($curl, CURLINFO_HEADER_OUT, true);
- //https请求
- if (1 == strpos("$" . $url, "https://")) {
- curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
- curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
- }
- //post请求
- if ($method == 'PUT' && !empty($data['body'])) {
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
- // 注意这里的'file'是上传地址指定的key名
- curl_setopt($curl, CURLOPT_POSTFIELDS, $data['body']);
- }
- if (!empty($data['xml'])) {
- curl_setopt($curl, CURLOPT_POSTFIELDS, $data['xml']);
- }
- list($content, $status) = [curl_exec($curl), curl_getinfo($curl), curl_close($curl)];
- $content = trim(substr($content, $status['header_size']));
- $this->response['content'] = $content;
- $this->response['code'] = $status['http_code'];
- $this->response['header'] = $status;
- $res = XML::parse($content);
- if ($res) {
- return $res;
- }
- return (intval($status["http_code"]) === 200) ? $content : false;
- }
- /**
- * 获取签名
- * @param string $method
- * @param string $urlPath
- * @param array $query
- * @param array $headers
- * @return array
- * @author 等风来
- * @email 136327134@qq.com
- * @date 2022/9/27
- */
- public function getSign(string $url, string $method, string $urlPath, array $query = [], array $headers = [])
- {
- return (new Signature($this->accessKey, $this->secretKey, ['signHost' => $url]))->signRequest($method, $urlPath, $query, $headers);
- }
- }
|