添加网站文件

This commit is contained in:
2025-12-22 13:59:40 +08:00
commit 117aaf83d1
19468 changed files with 2111999 additions and 0 deletions

188
vendor/qiniu/php-sdk/src/Qiniu/Auth.php vendored Normal file
View File

@@ -0,0 +1,188 @@
<?php
namespace Qiniu;
use Qiniu\Zone;
final class Auth
{
private $accessKey;
private $secretKey;
public function __construct($accessKey, $secretKey)
{
$this->accessKey = $accessKey;
$this->secretKey = $secretKey;
}
public function getAccessKey()
{
return $this->accessKey;
}
public function sign($data)
{
$hmac = hash_hmac('sha1', $data, $this->secretKey, true);
return $this->accessKey . ':' . \Qiniu\base64_urlSafeEncode($hmac);
}
public function signWithData($data)
{
$encodedData = \Qiniu\base64_urlSafeEncode($data);
return $this->sign($encodedData) . ':' . $encodedData;
}
public function signRequest($urlString, $body, $contentType = null)
{
$url = parse_url($urlString);
$data = '';
if (array_key_exists('path', $url)) {
$data = $url['path'];
}
if (array_key_exists('query', $url)) {
$data .= '?' . $url['query'];
}
$data .= "\n";
if ($body !== null && $contentType === 'application/x-www-form-urlencoded') {
$data .= $body;
}
return $this->sign($data);
}
public function verifyCallback($contentType, $originAuthorization, $url, $body)
{
$authorization = 'QBox ' . $this->signRequest($url, $body, $contentType);
return $originAuthorization === $authorization;
}
public function privateDownloadUrl($baseUrl, $expires = 3600)
{
$deadline = time() + $expires;
$pos = strpos($baseUrl, '?');
if ($pos !== false) {
$baseUrl .= '&e=';
} else {
$baseUrl .= '?e=';
}
$baseUrl .= $deadline;
$token = $this->sign($baseUrl);
return "$baseUrl&token=$token";
}
public function uploadToken($bucket, $key = null, $expires = 3600, $policy = null, $strictPolicy = true)
{
$deadline = time() + $expires;
$scope = $bucket;
if ($key !== null) {
$scope .= ':' . $key;
}
$args = self::copyPolicy($args, $policy, $strictPolicy);
$args['scope'] = $scope;
$args['deadline'] = $deadline;
$b = json_encode($args);
return $this->signWithData($b);
}
/**
*上传策略,参数规格详见
*http://developer.qiniu.com/docs/v6/api/reference/security/put-policy.html
*/
private static $policyFields = array(
'callbackUrl',
'callbackBody',
'callbackHost',
'callbackBodyType',
'callbackFetchKey',
'returnUrl',
'returnBody',
'endUser',
'saveKey',
'forceSaveKey',
'insertOnly',
'detectMime',
'mimeLimit',
'fsizeMin',
'fsizeLimit',
'persistentOps',
'persistentNotifyUrl',
'persistentPipeline',
'deleteAfterDays',
'fileType',
'isPrefixalScope',
);
private static function copyPolicy(&$policy, $originPolicy, $strictPolicy)
{
if ($originPolicy === null) {
return array();
}
foreach ($originPolicy as $key => $value) {
if (!$strictPolicy || in_array((string)$key, self::$policyFields, true)) {
$policy[$key] = $value;
}
}
return $policy;
}
public function authorization($url, $body = null, $contentType = null)
{
$authorization = 'QBox ' . $this->signRequest($url, $body, $contentType);
return array('Authorization' => $authorization);
}
public function authorizationV2($url, $method, $body = null, $contentType = null)
{
$urlItems = parse_url($url);
$host = $urlItems['host'];
if (isset($urlItems['port'])) {
$port = $urlItems['port'];
} else {
$port = '';
}
$path = $urlItems['path'];
if (isset($urlItems['query'])) {
$query = $urlItems['query'];
} else {
$query = '';
}
//write request uri
$toSignStr = $method . ' ' . $path;
if (!empty($query)) {
$toSignStr .= '?' . $query;
}
//write host and port
$toSignStr .= "\nHost: " . $host;
if (!empty($port)) {
$toSignStr .= ":" . $port;
}
//write content type
if (!empty($contentType)) {
$toSignStr .= "\nContent-Type: " . $contentType;
}
$toSignStr .= "\n\n";
//write body
if (!empty($body)) {
$toSignStr .= $body;
}
$sign = $this->sign($toSignStr);
$auth = 'Qiniu ' . $sign;
return array('Authorization' => $auth);
}
}

View File

@@ -0,0 +1,260 @@
<?php
namespace Qiniu\Cdn;
use Qiniu\Auth;
use Qiniu\Http\Error;
use Qiniu\Http\Client;
final class CdnManager
{
private $auth;
private $server;
public function __construct(Auth $auth)
{
$this->auth = $auth;
$this->server = 'http://fusion.qiniuapi.com';
}
/**
* @param array $urls 待刷新的文件链接数组
* @return array
*/
public function refreshUrls(array $urls)
{
return $this->refreshUrlsAndDirs($urls, array());
}
/**
* @param array $dirs 待刷新的文件链接数组
* @return array
* 目前客户默认没有目录刷新权限刷新会有400038报错参考https://developer.qiniu.com/fusion/api/1229/cache-refresh
* 需要刷新目录请工单联系技术支持 https://support.qiniu.com/tickets/category
*/
public function refreshDirs(array $dirs)
{
return $this->refreshUrlsAndDirs(array(), $dirs);
}
/**
* @param array $urls 待刷新的文件链接数组
* @param array $dirs 待刷新的目录链接数组
*
* @return array 刷新的请求回复和错误,参考 examples/cdn_manager.php 代码
* @link http://developer.qiniu.com/article/fusion/api/refresh.html
*
* 目前客户默认没有目录刷新权限刷新会有400038报错参考https://developer.qiniu.com/fusion/api/1229/cache-refresh
* 需要刷新目录请工单联系技术支持 https://support.qiniu.com/tickets/category
*/
public function refreshUrlsAndDirs(array $urls, array $dirs)
{
$req = array();
if (!empty($urls)) {
$req['urls'] = $urls;
}
if (!empty($dirs)) {
$req['dirs'] = $dirs;
}
$url = $this->server . '/v2/tune/refresh';
$body = json_encode($req);
return $this->post($url, $body);
}
/**
* 查询 CDN 刷新记录
*
* @param string $requestId 指定要查询记录所在的刷新请求id
* @param string $isDir 指定是否查询目录,取值为 yes/no默认不填则为两种类型记录都查询
* @param array $urls 要查询的url列表每个url可以是文件url也可以是目录url
* @param string $state 指定要查询记录的状态取值processingsuccessfailure
* @param int $pageNo 要求返回的页号默认为0
* @param int $pageSize 要求返回的页长度默认为100
* @param string $startTime 指定查询的开始日期格式2006-01-01
* @param string $endTime 指定查询的结束日期格式2006-01-01
* @return array
* @link https://developer.qiniu.com/fusion/api/1229/cache-refresh#4
*/
public function getCdnRefreshList(
$requestId = null,
$isDir = null,
$urls = array(),
$state = null,
$pageNo = 0,
$pageSize = 100,
$startTime = null,
$endTime = null
) {
$req = array();
\Qiniu\setWithoutEmpty($req, 'requestId', $requestId);
\Qiniu\setWithoutEmpty($req, 'isDir', $isDir);
\Qiniu\setWithoutEmpty($req, 'urls', $urls);
\Qiniu\setWithoutEmpty($req, 'state', $state);
\Qiniu\setWithoutEmpty($req, 'pageNo', $pageNo);
\Qiniu\setWithoutEmpty($req, 'pageSize', $pageSize);
\Qiniu\setWithoutEmpty($req, 'startTime', $startTime);
\Qiniu\setWithoutEmpty($req, 'endTime', $endTime);
$body = json_encode($req);
$url = $this->server . '/v2/tune/refresh/list';
return $this->post($url, $body);
}
/**
* @param array $urls 待预取的文件链接数组
*
* @return array 预取的请求回复和错误,参考 examples/cdn_manager.php 代码
*
* @link http://developer.qiniu.com/article/fusion/api/refresh.html
*/
public function prefetchUrls(array $urls)
{
$req = array(
'urls' => $urls,
);
$url = $this->server . '/v2/tune/prefetch';
$body = json_encode($req);
return $this->post($url, $body);
}
/**
* 查询 CDN 预取记录
*
* @param string $requestId 指定要查询记录所在的刷新请求id
* @param array $urls 要查询的url列表每个url可以是文件url也可以是目录url
* @param string $state 指定要查询记录的状态取值processingsuccessfailure
* @param int $pageNo 要求返回的页号默认为0
* @param int $pageSize 要求返回的页长度默认为100
* @param string $startTime 指定查询的开始日期格式2006-01-01
* @param string $endTime 指定查询的结束日期格式2006-01-01
* @return array
* @link https://developer.qiniu.com/fusion/api/1227/file-prefetching#4
*/
public function getCdnPrefetchList(
$requestId = null,
$urls = array(),
$state = null,
$pageNo = 0,
$pageSize = 100,
$startTime = null,
$endTime = null
) {
$req = array();
\Qiniu\setWithoutEmpty($req, 'requestId', $requestId);
\Qiniu\setWithoutEmpty($req, 'urls', $urls);
\Qiniu\setWithoutEmpty($req, 'state', $state);
\Qiniu\setWithoutEmpty($req, 'pageNo', $pageNo);
\Qiniu\setWithoutEmpty($req, 'pageSize', $pageSize);
\Qiniu\setWithoutEmpty($req, 'startTime', $startTime);
\Qiniu\setWithoutEmpty($req, 'endTime', $endTime);
$body = json_encode($req);
$url = $this->server . '/v2/tune/prefetch/list';
return $this->post($url, $body);
}
/**
* @param array $domains 待获取带宽数据的域名数组
* @param string $startDate 开始的日期,格式类似 2017-01-01
* @param string $endDate 结束的日期,格式类似 2017-01-01
* @param string $granularity 获取数据的时间间隔,可以是 5min, hour 或者 day
*
* @return array 带宽数据和错误信息,参考 examples/cdn_manager.php 代码
*
* @link http://developer.qiniu.com/article/fusion/api/traffic-bandwidth.html
*/
public function getBandwidthData(array $domains, $startDate, $endDate, $granularity)
{
$req = array();
$req['domains'] = implode(';', $domains);
$req['startDate'] = $startDate;
$req['endDate'] = $endDate;
$req['granularity'] = $granularity;
$url = $this->server . '/v2/tune/bandwidth';
$body = json_encode($req);
return $this->post($url, $body);
}
/**
* @param array $domains 待获取流量数据的域名数组
* @param string $startDate 开始的日期,格式类似 2017-01-01
* @param string $endDate 结束的日期,格式类似 2017-01-01
* @param string $granularity 获取数据的时间间隔,可以是 5min, hour 或者 day
*
* @return array 流量数据和错误信息,参考 examples/cdn_manager.php 代码
*
* @link http://developer.qiniu.com/article/fusion/api/traffic-bandwidth.html
*/
public function getFluxData(array $domains, $startDate, $endDate, $granularity)
{
$req = array();
$req['domains'] = implode(';', $domains);
$req['startDate'] = $startDate;
$req['endDate'] = $endDate;
$req['granularity'] = $granularity;
$url = $this->server . '/v2/tune/flux';
$body = json_encode($req);
return $this->post($url, $body);
}
/**
* @param array $domains 待获取日志下载链接的域名数组
* @param string $logDate 获取指定日期的日志下载链接,格式类似 2017-01-01
*
* @return array 日志下载链接数据和错误信息,参考 examples/cdn_manager.php 代码
*
* @link http://developer.qiniu.com/article/fusion/api/log.html
*/
public function getCdnLogList(array $domains, $logDate)
{
$req = array();
$req['domains'] = implode(';', $domains);
$req['day'] = $logDate;
$url = $this->server . '/v2/tune/log/list';
$body = json_encode($req);
return $this->post($url, $body);
}
private function post($url, $body)
{
$headers = $this->auth->authorization($url, $body, 'application/json');
$headers['Content-Type'] = 'application/json';
$ret = Client::post($url, $body, $headers);
if (!$ret->ok()) {
return array(null, new Error($url, $ret));
}
$r = ($ret->body === null) ? array() : $ret->json();
return array($r, null);
}
/**
* 构建时间戳防盗链鉴权的访问外链
*
* @param string $rawUrl 需要签名的资源url
* @param string $encryptKey 时间戳防盗链密钥
* @param string $durationInSeconds 链接的有效期(以秒为单位)
*
* @return string 带鉴权信息的资源外链,参考 examples/cdn_timestamp_antileech.php 代码
*/
public static function createTimestampAntiLeechUrl($rawUrl, $encryptKey, $durationInSeconds)
{
$parsedUrl = parse_url($rawUrl);
$deadline = time() + $durationInSeconds;
$expireHex = dechex($deadline);
$path = isset($parsedUrl['path']) ? $parsedUrl['path'] : '';
$strToSign = $encryptKey . $path . $expireHex;
$signStr = md5($strToSign);
if (isset($parsedUrl['query'])) {
$signedUrl = $rawUrl . '&sign=' . $signStr . '&t=' . $expireHex;
} else {
$signedUrl = $rawUrl . '?sign=' . $signStr . '&t=' . $expireHex;
}
return $signedUrl;
}
}

View File

@@ -0,0 +1,140 @@
<?php
namespace Qiniu;
final class Config
{
const SDK_VER = '7.3.0';
const BLOCK_SIZE = 4194304; //4*1024*1024 分块上传块大小,该参数为接口规格,不能修改
const RSF_HOST = 'rsf.qiniu.com';
const API_HOST = 'api.qiniu.com';
const RS_HOST = 'rs.qiniu.com'; //RS Host
const UC_HOST = 'uc.qbox.me'; //UC Host
const RTCAPI_HOST = 'http://rtc.qiniuapi.com';
const ARGUS_HOST = 'ai.qiniuapi.com';
const CASTER_HOST = 'pili-caster.qiniuapi.com';
const SMS_HOST="https://sms.qiniuapi.com";
const RTCAPI_VERSION = 'v3';
const SMS_VERSION='v1';
// Zone 空间对应的存储区域
public $region;
//BOOL 是否使用https域名
public $useHTTPS;
//BOOL 是否使用CDN加速上传域名
public $useCdnDomains;
// Zone Cache
private $regionCache;
// 构造函数
public function __construct(Region $z = null)
{
$this->zone = $z;
$this->useHTTPS = false;
$this->useCdnDomains = false;
$this->regionCache = array();
}
public function getUpHost($accessKey, $bucket)
{
$region = $this->getRegion($accessKey, $bucket);
if ($this->useHTTPS === true) {
$scheme = "https://";
} else {
$scheme = "http://";
}
$host = $region->srcUpHosts[0];
if ($this->useCdnDomains === true) {
$host = $region->cdnUpHosts[0];
}
return $scheme . $host;
}
public function getUpBackupHost($accessKey, $bucket)
{
$region = $this->getRegion($accessKey, $bucket);
if ($this->useHTTPS === true) {
$scheme = "https://";
} else {
$scheme = "http://";
}
$host = $region->cdnUpHosts[0];
if ($this->useCdnDomains === true) {
$host = $region->srcUpHosts[0];
}
return $scheme . $host;
}
public function getRsHost($accessKey, $bucket)
{
$region = $this->getRegion($accessKey, $bucket);
if ($this->useHTTPS === true) {
$scheme = "https://";
} else {
$scheme = "http://";
}
return $scheme . $region->rsHost;
}
public function getRsfHost($accessKey, $bucket)
{
$region = $this->getRegion($accessKey, $bucket);
if ($this->useHTTPS === true) {
$scheme = "https://";
} else {
$scheme = "http://";
}
return $scheme . $region->rsfHost;
}
public function getIovipHost($accessKey, $bucket)
{
$region = $this->getRegion($accessKey, $bucket);
if ($this->useHTTPS === true) {
$scheme = "https://";
} else {
$scheme = "http://";
}
return $scheme . $region->iovipHost;
}
public function getApiHost($accessKey, $bucket)
{
$region = $this->getRegion($accessKey, $bucket);
if ($this->useHTTPS === true) {
$scheme = "https://";
} else {
$scheme = "http://";
}
return $scheme . $region->apiHost;
}
private function getRegion($accessKey, $bucket)
{
$cacheId = "$accessKey:$bucket";
if (isset($this->regionCache[$cacheId])) {
$region = $this->regionCache[$cacheId];
} elseif (isset($this->zone)) {
$region = $this->zone;
$this->regionCache[$cacheId] = $region;
} else {
$region = Zone::queryZone($accessKey, $bucket);
$this->regionCache[$cacheId] = $region;
}
return $region;
}
}

76
vendor/qiniu/php-sdk/src/Qiniu/Etag.php vendored Normal file
View File

@@ -0,0 +1,76 @@
<?php
namespace Qiniu;
use Qiniu\Config;
final class Etag
{
private static function packArray($v, $a)
{
return call_user_func_array('pack', array_merge(array($v), (array)$a));
}
private static function blockCount($fsize)
{
return intval(($fsize + (Config::BLOCK_SIZE - 1)) / Config::BLOCK_SIZE);
}
private static function calcSha1($data)
{
$sha1Str = sha1($data, true);
$err = error_get_last();
if ($err !== null) {
return array(null, $err);
}
$byteArray = unpack('C*', $sha1Str);
return array($byteArray, null);
}
public static function sum($filename)
{
$fhandler = fopen($filename, 'r');
$err = error_get_last();
if ($err !== null) {
return array(null, $err);
}
$fstat = fstat($fhandler);
$fsize = $fstat['size'];
if ((int)$fsize === 0) {
fclose($fhandler);
return array('Fto5o-5ea0sNMlW_75VgGJCv2AcJ', null);
}
$blockCnt = self::blockCount($fsize);
$sha1Buf = array();
if ($blockCnt <= 1) {
array_push($sha1Buf, 0x16);
$fdata = fread($fhandler, Config::BLOCK_SIZE);
if ($err !== null) {
fclose($fhandler);
return array(null, $err);
}
list($sha1Code,) = self::calcSha1($fdata);
$sha1Buf = array_merge($sha1Buf, $sha1Code);
} else {
array_push($sha1Buf, 0x96);
$sha1BlockBuf = array();
for ($i = 0; $i < $blockCnt; $i++) {
$fdata = fread($fhandler, Config::BLOCK_SIZE);
list($sha1Code, $err) = self::calcSha1($fdata);
if ($err !== null) {
fclose($fhandler);
return array(null, $err);
}
$sha1BlockBuf = array_merge($sha1BlockBuf, $sha1Code);
}
$tmpData = self::packArray('C*', $sha1BlockBuf);
list($sha1Final,) = self::calcSha1($tmpData);
$sha1Buf = array_merge($sha1Buf, $sha1Final);
}
$etag = \Qiniu\base64_urlSafeEncode(self::packArray('C*', $sha1Buf));
return array($etag, null);
}
}

View File

@@ -0,0 +1,160 @@
<?php
namespace Qiniu\Http;
use Qiniu\Config;
use Qiniu\Http\Request;
use Qiniu\Http\Response;
final class Client
{
public static function get($url, array $headers = array())
{
$request = new Request('GET', $url, $headers);
return self::sendRequest($request);
}
public static function delete($url, array $headers = array())
{
$request = new Request('DELETE', $url, $headers);
return self::sendRequest($request);
}
public static function post($url, $body, array $headers = array())
{
$request = new Request('POST', $url, $headers, $body);
return self::sendRequest($request);
}
public static function PUT($url, $body, array $headers = array())
{
$request = new Request('PUT', $url, $headers, $body);
return self::sendRequest($request);
}
public static function multipartPost(
$url,
$fields,
$name,
$fileName,
$fileBody,
$mimeType = null,
array $headers = array()
) {
$data = array();
$mimeBoundary = md5(microtime());
foreach ($fields as $key => $val) {
array_push($data, '--' . $mimeBoundary);
array_push($data, "Content-Disposition: form-data; name=\"$key\"");
array_push($data, '');
array_push($data, $val);
}
array_push($data, '--' . $mimeBoundary);
$finalMimeType = empty($mimeType) ? 'application/octet-stream' : $mimeType;
$finalFileName = self::escapeQuotes($fileName);
array_push($data, "Content-Disposition: form-data; name=\"$name\"; filename=\"$finalFileName\"");
array_push($data, "Content-Type: $finalMimeType");
array_push($data, '');
array_push($data, $fileBody);
array_push($data, '--' . $mimeBoundary . '--');
array_push($data, '');
$body = implode("\r\n", $data);
// var_dump($data);exit;
$contentType = 'multipart/form-data; boundary=' . $mimeBoundary;
$headers['Content-Type'] = $contentType;
$request = new Request('POST', $url, $headers, $body);
return self::sendRequest($request);
}
private static function userAgent()
{
$sdkInfo = "QiniuPHP/" . Config::SDK_VER;
$systemInfo = php_uname("s");
$machineInfo = php_uname("m");
$envInfo = "($systemInfo/$machineInfo)";
$phpVer = phpversion();
$ua = "$sdkInfo $envInfo PHP/$phpVer";
return $ua;
}
public static function sendRequest($request)
{
$t1 = microtime(true);
$ch = curl_init();
$options = array(
CURLOPT_USERAGENT => self::userAgent(),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_HEADER => true,
CURLOPT_NOBODY => false,
CURLOPT_CUSTOMREQUEST => $request->method,
CURLOPT_URL => $request->url,
);
// Handle open_basedir & safe mode
if (!ini_get('safe_mode') && !ini_get('open_basedir')) {
$options[CURLOPT_FOLLOWLOCATION] = true;
}
if (!empty($request->headers)) {
$headers = array();
foreach ($request->headers as $key => $val) {
array_push($headers, "$key: $val");
}
$options[CURLOPT_HTTPHEADER] = $headers;
}
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
if (!empty($request->body)) {
$options[CURLOPT_POSTFIELDS] = $request->body;
}
curl_setopt_array($ch, $options);
$result = curl_exec($ch);
$t2 = microtime(true);
$duration = round($t2 - $t1, 3);
$ret = curl_errno($ch);
if ($ret !== 0) {
$r = new Response(-1, $duration, array(), null, curl_error($ch));
curl_close($ch);
return $r;
}
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$headers = self::parseHeaders(substr($result, 0, $header_size));
$body = substr($result, $header_size);
curl_close($ch);
return new Response($code, $duration, $headers, $body, null);
}
private static function parseHeaders($raw)
{
$headers = array();
$headerLines = explode("\r\n", $raw);
foreach ($headerLines as $line) {
$headerLine = trim($line);
$kv = explode(':', $headerLine);
if (count($kv) > 1) {
$kv[0] =self::ucwordsHyphen($kv[0]);
$headers[$kv[0]] = trim($kv[1]);
}
}
return $headers;
}
private static function escapeQuotes($str)
{
$find = array("\\", "\"");
$replace = array("\\\\", "\\\"");
return str_replace($find, $replace, $str);
}
private static function ucwordsHyphen($str)
{
return str_replace('- ', '-', ucwords(str_replace('-', '- ', $str)));
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace Qiniu\Http;
/**
* 七牛业务请求逻辑错误封装类主要用来解析API请求返回如下的内容
* <pre>
* {"error" : "detailed error message"}
* </pre>
*/
final class Error
{
private $url;
private $response;
public function __construct($url, $response)
{
$this->url = $url;
$this->response = $response;
}
public function code()
{
return $this->response->statusCode;
}
public function getResponse()
{
return $this->response;
}
public function message()
{
return $this->response->error;
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Qiniu\Http;
final class Request
{
public $url;
public $headers;
public $body;
public $method;
public function __construct($method, $url, array $headers = array(), $body = null)
{
$this->method = strtoupper($method);
$this->url = $url;
$this->headers = $headers;
$this->body = $body;
}
}

View File

@@ -0,0 +1,176 @@
<?php
namespace Qiniu\Http;
/**
* HTTP response Object
*/
final class Response
{
public $statusCode;
public $headers;
public $body;
public $error;
private $jsonData;
public $duration;
/** @var array Mapping of status codes to reason phrases */
private static $statusTexts = array(
100 => 'Continue',
101 => 'Switching Protocols',
102 => 'Processing',
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
207 => 'Multi-Status',
208 => 'Already Reported',
226 => 'IM Used',
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found',
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
307 => 'Temporary Redirect',
308 => 'Permanent Redirect',
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
422 => 'Unprocessable Entity',
423 => 'Locked',
424 => 'Failed Dependency',
425 => 'Reserved for WebDAV advanced collections expired proposal',
426 => 'Upgrade required',
428 => 'Precondition Required',
429 => 'Too Many Requests',
431 => 'Request Header Fields Too Large',
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported',
506 => 'Variant Also Negotiates (Experimental)',
507 => 'Insufficient Storage',
508 => 'Loop Detected',
510 => 'Not Extended',
511 => 'Network Authentication Required',
);
/**
* @param int $code 状态码
* @param double $duration 请求时长
* @param array $headers 响应头部
* @param string $body 响应内容
* @param string $error 错误描述
*/
public function __construct($code, $duration, array $headers = array(), $body = null, $error = null)
{
$this->statusCode = $code;
$this->duration = $duration;
$this->headers = $headers;
$this->body = $body;
$this->error = $error;
$this->jsonData = null;
if ($error !== null) {
return;
}
if ($body === null) {
if ($code >= 400) {
$this->error = self::$statusTexts[$code];
}
return;
}
if (self::isJson($headers)) {
try {
$jsonData = self::bodyJson($body);
if ($code >= 400) {
$this->error = $body;
if ($jsonData['error'] !== null) {
$this->error = $jsonData['error'];
}
}
$this->jsonData = $jsonData;
} catch (\InvalidArgumentException $e) {
$this->error = $body;
if ($code >= 200 && $code < 300) {
$this->error = $e->getMessage();
}
}
} elseif ($code >= 400) {
$this->error = $body;
}
return;
}
public function json()
{
return $this->jsonData;
}
private static function bodyJson($body)
{
return \Qiniu\json_decode((string) $body, true, 512);
}
public function xVia()
{
$via = $this->headers['X-Via'];
if ($via === null) {
$via = $this->headers['X-Px'];
}
if ($via === null) {
$via = $this->headers['Fw-Via'];
}
return $via;
}
public function xLog()
{
return $this->headers['X-Log'];
}
public function xReqId()
{
return $this->headers['X-Reqid'];
}
public function ok()
{
return $this->statusCode >= 200 && $this->statusCode < 300 && $this->error === null;
}
public function needRetry()
{
$code = $this->statusCode;
if ($code < 0 || ($code / 100 === 5 and $code !== 579) || $code === 996) {
return true;
}
}
private static function isJson($headers)
{
return array_key_exists('content-type', $headers) || array_key_exists('Content-Type', $headers) &&
strpos($headers['Content-Type'], 'application/json') === 0;
}
}

View File

@@ -0,0 +1,292 @@
<?php
namespace Qiniu\Processing;
use Qiniu;
/**
* 主要涉及图片链接拼接
*
* @link http://developer.qiniu.com/code/v6/api/kodo-api/image/imageview2.html
*/
final class ImageUrlBuilder
{
/**
* mode合法范围值
*
* @var array
*/
protected $modeArr = array(0, 1, 2, 3, 4, 5);
/**
* format合法值
*
* @var array
*/
protected $formatArr = array('psd', 'jpeg', 'png', 'gif', 'webp', 'tiff', 'bmp');
/**
* 水印图片位置合法值
*
* @var array
*/
protected $gravityArr = array(
'NorthWest',
'North',
'NorthEast',
'West',
'Center',
'East',
'SouthWest',
'South',
'SouthEast'
);
/**
* 缩略图链接拼接
*
* @param string $url 图片链接
* @param int $mode 缩略模式
* @param int $width 宽度
* @param int $height 长度
* @param string $format 输出类型
* @param int $quality 图片质量
* @param int $interlace 是否支持渐进显示
* @param int $ignoreError 忽略结果
* @return string
* @link http://developer.qiniu.com/code/v6/api/kodo-api/image/imageview2.html
* @author Sherlock Ren <sherlock_ren@icloud.com>
*/
public function thumbnail(
$url,
$mode,
$width,
$height,
$format = null,
$interlace = null,
$quality = null,
$ignoreError = 1
) {
// url合法效验
if (!$this->isUrl($url)) {
return $url;
}
// 参数合法性效验
if (!in_array(intval($mode), $this->modeArr, true)) {
return $url;
}
if (!$width || !$height) {
return $url;
}
$thumbStr = 'imageView2/' . $mode . '/w/' . $width . '/h/' . $height . '/';
// 拼接输出格式
if (!is_null($format)
&& in_array($format, $this->formatArr)
) {
$thumbStr .= 'format/' . $format . '/';
}
// 拼接渐进显示
if (!is_null($interlace)
&& in_array(intval($interlace), array(0, 1), true)
) {
$thumbStr .= 'interlace/' . $interlace . '/';
}
// 拼接图片质量
if (!is_null($quality)
&& intval($quality) >= 0
&& intval($quality) <= 100
) {
$thumbStr .= 'q/' . $quality . '/';
}
$thumbStr .= 'ignore-error/' . $ignoreError . '/';
// 如果有query_string用|线分割实现多参数
return $url . ($this->hasQuery($url) ? '|' : '?') . $thumbStr;
}
/**
* 图片水印
*
* @param string $url 图片链接
* @param string $image 水印图片链接
* @param int $dissolve 透明度
* @param string $gravity 水印位置
* @param int $dx 横轴边距
* @param int $dy 纵轴边距
* @param int $watermarkScale 自适应原图的短边比例
* @return string
* @link http://developer.qiniu.com/code/v6/api/kodo-api/image/watermark.html
* @author Sherlock Ren <sherlock_ren@icloud.com>
*/
public function waterImg(
$url,
$image,
$dissolve = 100,
$gravity = 'SouthEast',
$dx = null,
$dy = null,
$watermarkScale = null
) {
// url合法效验
if (!$this->isUrl($url)) {
return $url;
}
$waterStr = 'watermark/1/image/' . \Qiniu\base64_urlSafeEncode($image) . '/';
// 拼接水印透明度
if (is_numeric($dissolve)
&& $dissolve <= 100
) {
$waterStr .= 'dissolve/' . $dissolve . '/';
}
// 拼接水印位置
if (in_array($gravity, $this->gravityArr, true)) {
$waterStr .= 'gravity/' . $gravity . '/';
}
// 拼接横轴边距
if (!is_null($dx)
&& is_numeric($dx)
) {
$waterStr .= 'dx/' . $dx . '/';
}
// 拼接纵轴边距
if (!is_null($dy)
&& is_numeric($dy)
) {
$waterStr .= 'dy/' . $dy . '/';
}
// 拼接自适应原图的短边比例
if (!is_null($watermarkScale)
&& is_numeric($watermarkScale)
&& $watermarkScale > 0
&& $watermarkScale < 1
) {
$waterStr .= 'ws/' . $watermarkScale . '/';
}
// 如果有query_string用|线分割实现多参数
return $url . ($this->hasQuery($url) ? '|' : '?') . $waterStr;
}
/**
* 文字水印
*
* @param string $url 图片链接
* @param string $text 文字
* @param string $font 文字字体
* @param string $fontSize 文字字号
* @param string $fontColor 文字颜色
* @param int $dissolve 透明度
* @param string $gravity 水印位置
* @param int $dx 横轴边距
* @param int $dy 纵轴边距
* @return string
* @link http://developer.qiniu.com/code/v6/api/kodo-api/image/watermark.html#text-watermark
* @author Sherlock Ren <sherlock_ren@icloud.com>
*/
public function waterText(
$url,
$text,
$font = '黑体',
$fontSize = 0,
$fontColor = null,
$dissolve = 100,
$gravity = 'SouthEast',
$dx = null,
$dy = null
) {
// url合法效验
if (!$this->isUrl($url)) {
return $url;
}
$waterStr = 'watermark/2/text/'
. \Qiniu\base64_urlSafeEncode($text) . '/font/'
. \Qiniu\base64_urlSafeEncode($font) . '/';
// 拼接文字大小
if (is_int($fontSize)) {
$waterStr .= 'fontsize/' . $fontSize . '/';
}
// 拼接文字颜色
if (!is_null($fontColor)
&& $fontColor
) {
$waterStr .= 'fill/' . \Qiniu\base64_urlSafeEncode($fontColor) . '/';
}
// 拼接水印透明度
if (is_numeric($dissolve)
&& $dissolve <= 100
) {
$waterStr .= 'dissolve/' . $dissolve . '/';
}
// 拼接水印位置
if (in_array($gravity, $this->gravityArr, true)) {
$waterStr .= 'gravity/' . $gravity . '/';
}
// 拼接横轴边距
if (!is_null($dx)
&& is_numeric($dx)
) {
$waterStr .= 'dx/' . $dx . '/';
}
// 拼接纵轴边距
if (!is_null($dy)
&& is_numeric($dy)
) {
$waterStr .= 'dy/' . $dy . '/';
}
// 如果有query_string用|线分割实现多参数
return $url . ($this->hasQuery($url) ? '|' : '?') . $waterStr;
}
/**
* 效验url合法性
*
* @param string $url url链接
* @return string
* @author Sherlock Ren <sherlock_ren@icloud.com>
*/
protected function isUrl($url)
{
$urlArr = parse_url($url);
return $urlArr['scheme']
&& in_array($urlArr['scheme'], array('http', 'https'))
&& $urlArr['host']
&& $urlArr['path'];
}
/**
* 检测是否有query
*
* @param string $url url链接
* @return string
* @author Sherlock Ren <sherlock_ren@icloud.com>
*/
protected function hasQuery($url)
{
$urlArr = parse_url($url);
return !empty($urlArr['query']);
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace Qiniu\Processing;
use Qiniu\Http\Client;
use Qiniu\Http\Error;
final class Operation
{
private $auth;
private $token_expire;
private $domain;
public function __construct($domain, $auth = null, $token_expire = 3600)
{
$this->auth = $auth;
$this->domain = $domain;
$this->token_expire = $token_expire;
}
/**
* 对资源文件进行处理
*
* @param string $key 待处理的资源文件名
* @param string $fops string|array fop操作多次fop操作以array的形式传入。
* eg. imageView2/1/w/200/h/200, imageMogr2/thumbnail/!75px
*
* @return array 文件处理后的结果及错误。
*
* @link http://developer.qiniu.com/docs/v6/api/reference/fop/
*/
public function execute($key, $fops)
{
$url = $this->buildUrl($key, $fops);
$resp = Client::get($url);
if (!$resp->ok()) {
return array(null, new Error($url, $resp));
}
if ($resp->json() !== null) {
return array($resp->json(), null);
}
return array($resp->body, null);
}
public function buildUrl($key, $fops, $protocol = 'http')
{
if (is_array($fops)) {
$fops = implode('|', $fops);
}
$url = $protocol . "://$this->domain/$key?$fops";
if ($this->auth !== null) {
$url = $this->auth->privateDownloadUrl($url, $this->token_expire);
}
return $url;
}
}

View File

@@ -0,0 +1,94 @@
<?php
namespace Qiniu\Processing;
use Qiniu\Config;
use Qiniu\Http\Error;
use Qiniu\Http\Client;
/**
* 持久化处理类,该类用于主动触发异步持久化操作.
*
* @link http://developer.qiniu.com/docs/v6/api/reference/fop/pfop/pfop.html
*/
final class PersistentFop
{
/**
* @var 账号管理密钥对Auth对象
*/
private $auth;
/*
* @var 配置对象Config 对象
* */
private $config;
public function __construct($auth, $config = null)
{
$this->auth = $auth;
if ($config == null) {
$this->config = new Config();
} else {
$this->config = $config;
}
}
/**
* 对资源文件进行异步持久化处理
* @param string $bucket 资源所在空间
* @param string $key 待处理的源文件
* @param string $fops string|array 待处理的pfop操作多个pfop操作以array的形式传入。
* eg. avthumb/mp3/ab/192k, vframe/jpg/offset/7/w/480/h/360
* @param string $pipeline 资源处理队列
* @param string $notify_url 处理结果通知地址
* @param bool $force 是否强制执行一次新的指令
*
*
* @return array 返回持久化处理的persistentId, 和返回的错误。
*
* @link http://developer.qiniu.com/docs/v6/api/reference/fop/
*/
public function execute($bucket, $key, $fops, $pipeline = null, $notify_url = null, $force = false)
{
if (is_array($fops)) {
$fops = implode(';', $fops);
}
$params = array('bucket' => $bucket, 'key' => $key, 'fops' => $fops);
\Qiniu\setWithoutEmpty($params, 'pipeline', $pipeline);
\Qiniu\setWithoutEmpty($params, 'notifyURL', $notify_url);
if ($force) {
$params['force'] = 1;
}
$data = http_build_query($params);
$scheme = "http://";
if ($this->config->useHTTPS === true) {
$scheme = "https://";
}
$url = $scheme . Config::API_HOST . '/pfop/';
$headers = $this->auth->authorization($url, $data, 'application/x-www-form-urlencoded');
$headers['Content-Type'] = 'application/x-www-form-urlencoded';
$response = Client::post($url, $data, $headers);
if (!$response->ok()) {
return array(null, new Error($url, $response));
}
$r = $response->json();
$id = $r['persistentId'];
return array($id, null);
}
public function status($id)
{
$scheme = "http://";
if ($this->config->useHTTPS === true) {
$scheme = "https://";
}
$url = $scheme . Config::API_HOST . "/status/get/prefop?id=$id";
$response = Client::get($url);
if (!$response->ok()) {
return array(null, new Error($url, $response));
}
return array($response->json(), null);
}
}

View File

@@ -0,0 +1,196 @@
<?php
namespace Qiniu;
use Qiniu\Http\Client;
use Qiniu\Http\Error;
class Region
{
//源站上传域名
public $srcUpHosts;
//CDN加速上传域名
public $cdnUpHosts;
//资源管理域名
public $rsHost;
//资源列举域名
public $rsfHost;
//资源处理域名
public $apiHost;
//IOVIP域名
public $iovipHost;
//构造一个Region对象
public function __construct(
$srcUpHosts = array(),
$cdnUpHosts = array(),
$rsHost = "rs.qiniu.com",
$rsfHost = "rsf.qiniu.com",
$apiHost = "api.qiniu.com",
$iovipHost = null
) {
$this->srcUpHosts = $srcUpHosts;
$this->cdnUpHosts = $cdnUpHosts;
$this->rsHost = $rsHost;
$this->rsfHost = $rsfHost;
$this->apiHost = $apiHost;
$this->iovipHost = $iovipHost;
}
//华东机房
public static function regionHuadong()
{
$regionHuadong = new Region(
array("up.qiniup.com", 'up-jjh.qiniup.com', 'up-xs.qiniup.com'),
array('upload.qiniup.com', 'upload-jjh.qiniup.com', 'upload-xs.qiniup.com'),
'rs.qbox.me',
'rsf.qbox.me',
'api.qiniu.com',
'iovip.qbox.me'
);
return $regionHuadong;
}
//华东机房内网上传
public static function qvmRegionHuadong()
{
$qvmRegionHuadong = new Region(
array("free-qvm-z0-xs.qiniup.com"),
'rs.qbox.me',
'rsf.qbox.me',
'api.qiniu.com',
'iovip.qbox.me'
);
return $qvmRegionHuadong;
}
//华北机房内网上传
public static function qvmRegionHuabei()
{
$qvmRegionHuabei = new Region(
array("free-qvm-z1-zz.qiniup.com"),
"rs-z1.qbox.me",
"rsf-z1.qbox.me",
"api-z1.qiniu.com",
"iovip-z1.qbox.me"
);
return $qvmRegionHuabei;
}
//华北机房
public static function regionHuabei()
{
$regionHuabei = new Region(
array('up-z1.qiniup.com'),
array('upload-z1.qiniup.com'),
"rs-z1.qbox.me",
"rsf-z1.qbox.me",
"api-z1.qiniu.com",
"iovip-z1.qbox.me"
);
return $regionHuabei;
}
//华南机房
public static function regionHuanan()
{
$regionHuanan = new Region(
array('up-z2.qiniup.com', 'up-dg.qiniup.com', 'up-fs.qiniup.com'),
array('upload-z2.qiniup.com', 'upload-dg.qiniup.com', 'upload-fs.qiniup.com'),
"rs-z2.qbox.me",
"rsf-z2.qbox.me",
"api-z2.qiniu.com",
"iovip-z2.qbox.me"
);
return $regionHuanan;
}
//北美机房
public static function regionNorthAmerica()
{
//北美机房
$regionNorthAmerica = new Region(
array('up-na0.qiniup.com'),
array('upload-na0.qiniup.com'),
"rs-na0.qbox.me",
"rsf-na0.qbox.me",
"api-na0.qiniu.com",
"iovip-na0.qbox.me"
);
return $regionNorthAmerica;
}
//新加坡机房
public static function regionSingapore()
{
//新加坡机房
$regionSingapore = new Region(
array('up-as0.qiniup.com'),
array('upload-as0.qiniup.com'),
"rs-as0.qbox.me",
"rsf-as0.qbox.me",
"api-as0.qiniu.com",
"iovip-as0.qbox.me"
);
return $regionSingapore;
}
/*
* GET /v2/query?ak=<ak>&&bucket=<bucket>
**/
public static function queryRegion($ak, $bucket)
{
$Region = new Region();
$url = Config::API_HOST . '/v2/query' . "?ak=$ak&bucket=$bucket";
$ret = Client::Get($url);
if (!$ret->ok()) {
return array(null, new Error($url, $ret));
}
$r = ($ret->body === null) ? array() : $ret->json();
//parse Region;
$iovipHost = $r['io']['src']['main'][0];
$Region->iovipHost = $iovipHost;
$accMain = $r['up']['acc']['main'][0];
array_push($Region->cdnUpHosts, $accMain);
if (isset($r['up']['acc']['backup'])) {
foreach ($r['up']['acc']['backup'] as $key => $value) {
array_push($Region->cdnUpHosts, $value);
}
}
$srcMain = $r['up']['src']['main'][0];
array_push($Region->srcUpHosts, $srcMain);
if (isset($r['up']['src']['backup'])) {
foreach ($r['up']['src']['backup'] as $key => $value) {
array_push($Region->srcUpHosts, $value);
}
}
//set specific hosts
if (strstr($Region->iovipHost, "z1") !== false) {
$Region->rsHost = "rs-z1.qbox.me";
$Region->rsfHost = "rsf-z1.qbox.me";
$Region->apiHost = "api-z1.qiniu.com";
} elseif (strstr($Region->iovipHost, "z2") !== false) {
$Region->rsHost = "rs-z2.qbox.me";
$Region->rsfHost = "rsf-z2.qbox.me";
$Region->apiHost = "api-z2.qiniu.com";
} elseif (strstr($Region->iovipHost, "na0") !== false) {
$Region->rsHost = "rs-na0.qbox.me";
$Region->rsfHost = "rsf-na0.qbox.me";
$Region->apiHost = "api-na0.qiniu.com";
} elseif (strstr($Region->iovipHost, "as0") !== false) {
$Region->rsHost = "rs-as0.qbox.me";
$Region->rsfHost = "rsf-as0.qbox.me";
$Region->apiHost = "api-as0.qiniu.com";
} else {
$Region->rsHost = "rs.qbox.me";
$Region->rsfHost = "rsf.qbox.me";
$Region->apiHost = "api.qiniu.com";
}
return $Region;
}
}

View File

@@ -0,0 +1,234 @@
<?php
namespace Qiniu\Rtc;
use Qiniu\Auth;
use Qiniu\Config;
use Qiniu\Http\Error;
use Qiniu\Http\Client;
class AppClient
{
private $auth;
private $baseURL;
public function __construct(Auth $auth)
{
$this->auth = $auth;
$this->baseURL = sprintf("%s/%s/apps", Config::RTCAPI_HOST, Config::RTCAPI_VERSION);
}
/**
* 创建应用
*
* @param string $hub 绑定的直播 hub
* @param string $title app 的名称 注意Title 不是唯一标识,重复 create 动作将生成多个 app
* @param int $maxUsers 连麦房间支持的最大在线人数
* @param bool $noAutoKickUser 禁止自动踢人(抢流),默认为 false
* @return array
* @link https://doc.qnsdk.com/rtn/docs/server_overview#2_1
*/
public function createApp($hub, $title, $maxUsers = null, $noAutoKickUser = null)
{
$params = array();
$params['hub'] = $hub;
$params['title'] = $title;
if (!empty($maxUsers)) {
$params['maxUsers'] = $maxUsers;
}
if ($noAutoKickUser !== null) {
$params['noAutoKickUser'] = $noAutoKickUser;
}
$body = json_encode($params);
return $this->post($this->baseURL, $body);
}
/**
* 更新一个应用的配置信息
*
* @param string $appId app 的唯一标识,创建的时候由系统生成
* @param string $hub app 的名称,可选
* @param string $title 绑定的直播 hub可选用于合流后 rtmp 推流
* @param int $maxUsers 连麦房间支持的最大在线人数,可选
* @param bool $noAutoKickUser 禁止自动踢人,可选
* @param null $mergePublishRtmp 连麦合流转推 RTMP 的配置,可选择。其详细配置可以参考文档
* @return array
* @link https://doc.qnsdk.com/rtn/docs/server_overview#2_1
*/
public function updateApp($appId, $hub, $title, $maxUsers = null, $noAutoKickUser = null, $mergePublishRtmp = null)
{
$url = $this->baseURL . '/' . $appId;
$params = array();
$params['hub'] = $hub;
$params['title'] = $title;
if (!empty($maxUsers)) {
$params['maxUsers'] = $maxUsers;
}
if ($noAutoKickUser !== null) {
$params['noAutoKickUser'] = $noAutoKickUser;
}
if (!empty($mergePublishRtmp)) {
$params['mergePublishRtmp'] = $mergePublishRtmp;
}
$body = json_encode($params);
return $this->post($url, $body);
}
/**
* 获取应用信息
*
* @param string $appId
* @return array
* @link https://doc.qnsdk.com/rtn/docs/server_overview#2_1
*/
public function getApp($appId)
{
$url = $this->baseURL . '/' . $appId;
return $this->get($url);
}
/**
* 删除应用
*
* @param string $appId app 的唯一标识,创建的时候由系统生成
* @return array
* @link https://doc.qnsdk.com/rtn/docs/server_overview#2_1
*/
public function deleteApp($appId)
{
$url = $this->baseURL . '/' . $appId;
return $this->delete($url);
}
/**
* 获取房间内用户列表
*
* @param string $appId app 的唯一标识,创建的时候由系统生成
* @param string $roomName 操作所查询的连麦房间
* @return array
* @link https://doc.qnsdk.com/rtn/docs/server_overview#2_2
*/
public function listUser($appId, $roomName)
{
$url = sprintf("%s/%s/rooms/%s/users", $this->baseURL, $appId, $roomName);
return $this->get($url);
}
/**
* 指定一个用户踢出房间
*
* @param string $appId app 的唯一标识,创建的时候由系统生成
* @param string $roomName 连麦房间
* @param string $userId 操作所剔除的用户
* @return mixed
* @link https://doc.qnsdk.com/rtn/docs/server_overview#2_2
*/
public function kickUser($appId, $roomName, $userId)
{
$url = sprintf("%s/%s/rooms/%s/users/%s", $this->baseURL, $appId, $roomName, $userId);
return $this->delete($url);
}
/**
* 停止一个房间的合流转推
*
* @param string $appId
* @param string $roomName
* @return array
* @link https://doc.qnsdk.com/rtn/docs/server_overview#2_2
*/
public function stopMerge($appId, $roomName)
{
$url = sprintf("%s/%s/rooms/%s/merge", $this->baseURL, $appId, $roomName);
return $this->delete($url);
}
/**
* 获取应用中活跃房间
*
* @param string $appId 连麦房间所属的 app
* @param null $prefix 所查询房间名的前缀索引,可以为空。
* @param int $offset 分页查询的位移标记
* @param int $limit 此次查询的最大长度
* @return array
* @link https://doc.qnsdk.com/rtn/docs/server_overview#2_2
*/
public function listActiveRooms($appId, $prefix = null, $offset = null, $limit = null)
{
$query = array();
if (isset($prefix)) {
$query['prefix'] = $prefix;
}
if (isset($offset)) {
$query['offset'] = $offset;
}
if (isset($limit)) {
$query['limit'] = $limit;
}
if (isset($query) && !empty($query)) {
$query = '?' . http_build_query($query);
$url = sprintf("%s/%s/rooms%s", $this->baseURL, $appId, $query);
} else {
$url = sprintf("%s/%s/rooms", $this->baseURL, $appId);
}
return $this->get($url);
}
/**
* 生成加入房间的令牌
*
* @param string $appId app 的唯一标识,创建的时候由系统生成
* @param string $roomName 房间名称,需满足规格 ^[a-zA-Z0-9_-]{3,64}$
* @param string $userId 请求加入房间的用户 ID需满足规格 ^[a-zA-Z0-9_-]{3,50}$
* @param int $expireAt 鉴权的有效时间传入以秒为单位的64位 Unix 绝对时间
* @param string $permission 该用户的房间管理权限,"admin" 或 "user",默认为 "user"
* @return string
* @link https://doc.qnsdk.com/rtn/docs/server_overview#1
*/
public function appToken($appId, $roomName, $userId, $expireAt, $permission)
{
$params = array();
$params['appId'] = $appId;
$params['userId'] = $userId;
$params['roomName'] = $roomName;
$params['permission'] = $permission;
$params['expireAt'] = $expireAt;
$appAccessString = json_encode($params);
return $this->auth->signWithData($appAccessString);
}
private function get($url, $cType = null)
{
$rtcToken = $this->auth->authorizationV2($url, "GET", null, $cType);
$rtcToken['Content-Type'] = $cType;
$ret = Client::get($url, $rtcToken);
if (!$ret->ok()) {
return array(null, new Error($url, $ret));
}
return array($ret->json(), null);
}
private function delete($url, $contentType = 'application/json')
{
$rtcToken = $this->auth->authorizationV2($url, "DELETE", null, $contentType);
$rtcToken['Content-Type'] = $contentType;
$ret = Client::delete($url, $rtcToken);
if (!$ret->ok()) {
return array(null, new Error($url, $ret));
}
return array($ret->json(), null);
}
private function post($url, $body, $contentType = 'application/json')
{
$rtcToken = $this->auth->authorizationV2($url, "POST", $body, $contentType);
$rtcToken['Content-Type'] = $contentType;
$ret = Client::post($url, $body, $rtcToken);
if (!$ret->ok()) {
return array(null, new Error($url, $ret));
}
$r = ($ret->body === null) ? array() : $ret->json();
return array($r, null);
}
}

View File

@@ -0,0 +1,380 @@
<?php
namespace Qiniu\Sms;
use Qiniu\Auth;
use Qiniu\Config;
use Qiniu\Http\Error;
use Qiniu\Http\Client;
class Sms
{
private $auth;
private $baseURL;
public function __construct(Auth $auth)
{
$this->auth = $auth;
$this->baseURL = sprintf("%s/%s/", Config::SMS_HOST, Config::SMS_VERSION);
}
/**
* 创建签名
*
* @param string $signature 签名
* @param string $source 签名来源,申请签名时必须指定签名来源
* @param string $pics 签名对应的资质证明图片进行 base64 编码格式转换后的字符串,可选
* @return array
*
* @link https://developer.qiniu.com/sms/api/5844/sms-api-create-signature
*/
public function createSignature($signature, $source, $pics = null)
{
$params = array();
$params['signature'] = $signature;
$params['source'] = $source;
if (!empty($pics)) {
$params['pics'] = array($this->imgToBase64($pics));
}
$body = json_encode($params);
$url = $this->baseURL . 'signature';
return $this->post($url, $body);
}
/**
* 编辑签名
*
* @param string $id 签名 ID
* @param string $signature 签名
* @param string $source 签名来源
* @param string $pics 签名对应的资质证明图片进行 base64 编码格式转换后的字符串,可选
* @return array
* @link https://developer.qiniu.com/sms/api/5890/sms-api-edit-signature
*/
public function updateSignature($id, $signature, $source, $pics = null)
{
$params = array();
$params['signature'] = $signature;
$params['source'] = $source;
if (!empty($pics)) {
$params['pics'] = array($this->imgToBase64($pics));
}
$body = json_encode($params);
$url = $this->baseURL . 'signature/' . $id;
return $this->PUT($url, $body);
}
/**
* 列出签名
*
* @param string $audit_status 审核状态:"passed"(通过), "rejected"(未通过), "reviewing"(审核中)
* @param int $page 页码。默认为 1
* @param int $page_size 分页大小。默认为 20
* @return array
* @link https://developer.qiniu.com/sms/api/5889/sms-api-query-signature
*/
public function querySignature($audit_status = null, $page = 1, $page_size = 20)
{
$url = sprintf(
"%s?audit_status=%s&page=%s&page_size=%s",
$this->baseURL . 'signature',
$audit_status,
$page,
$page_size
);
return $this->get($url);
}
/**
* 查询单个签名
*
* @param string $signature_id
* @return array
* @link https://developer.qiniu.com/sms/api/5970/query-a-single-signature
*/
public function checkSingleSignature($signature_id)
{
$url = sprintf(
"%s/%s",
$this->baseURL . 'signature',
$signature_id
);
return $this->get($url);
}
/**
* 删除签名
*
* @param string $signature_id 签名 ID
* @return array
* @link https://developer.qiniu.com/sms/api/5891/sms-api-delete-signature
*/
public function deleteSignature($signature_id)
{
$url = $this->baseURL . 'signature/' . $signature_id;
return $this->delete($url);
}
/**
* 创建模板
*
* @param string $name 模板名称
* @param string $template 模板内容 可设置自定义变量,发送短信时候使用,参考:${code}
* @param string $type notification通知类,verification验证码,marketing营销类,voice语音类
* @param string $description 申请理由简述
* @param string $signature_id 已经审核通过的签名
* @return array array
* @link https://developer.qiniu.com/sms/api/5893/sms-api-create-template
*/
public function createTemplate(
$name,
$template,
$type,
$description,
$signature_id
) {
$params = array();
$params['name'] = $name;
$params['template'] = $template;
$params['type'] = $type;
$params['description'] = $description;
$params['signature_id'] = $signature_id;
$body = json_encode($params);
$url = $this->baseURL . 'template';
return $this->post($url, $body);
}
/**
* 列出模板
*
* @param string $audit_status 审核状态passed (通过), rejected (未通过), reviewing (审核中)
* @param int $page 页码。默认为 1
* @param int $page_size 分页大小。默认为 20
* @return array
* @link https://developer.qiniu.com/sms/api/5894/sms-api-query-template
*/
public function queryTemplate($audit_status = null, $page = 1, $page_size = 20)
{
$url = sprintf(
"%s?audit_status=%s&page=%s&page_size=%s",
$this->baseURL . 'template',
$audit_status,
$page,
$page_size
);
return $this->get($url);
}
/**
* 查询单个模版
*
* @param string $template_id 模版ID
* @return array
* @link https://developer.qiniu.com/sms/api/5969/query-a-single-template
*/
public function querySingleTemplate($template_id)
{
$url = sprintf(
"%s/%s",
$this->baseURL . 'template',
$template_id
);
return $this->get($url);
}
/**
* 编辑模板
*
* @param string $id 模板 ID
* @param string $name 模板名称
* @param string $template 模板内容
* @param string $description 申请理由简述
* @param string $signature_id 已经审核通过的签名 ID
* @return array
* @link https://developer.qiniu.com/sms/api/5895/sms-api-edit-template
*/
public function updateTemplate(
$id,
$name,
$template,
$description,
$signature_id
) {
$params = array();
$params['name'] = $name;
$params['template'] = $template;
$params['description'] = $description;
$params['signature_id'] = $signature_id;
$body = json_encode($params);
$url = $this->baseURL . 'template/' . $id;
return $this->PUT($url, $body);
}
/**
* 删除模板
*
* @param string $template_id 模板 ID
* @return array
* @link https://developer.qiniu.com/sms/api/5896/sms-api-delete-template
*/
public function deleteTemplate($template_id)
{
$url = $this->baseURL . 'template/' . $template_id;
return $this->delete($url);
}
/**
* 发送短信
*
* @param string $template_id 模板 ID
* @param array $mobiles 手机号
* @param array $parameters 自定义模板变量变量设置在创建模板时参数template指定
* @return array
* @link https://developer.qiniu.com/sms/api/5897/sms-api-send-message
*/
public function sendMessage($template_id, $mobiles, $parameters = null)
{
$params = array();
$params['template_id'] = $template_id;
$params['mobiles'] = $mobiles;
if (!empty($parameters)) {
$params['parameters'] = $parameters;
}
$body = json_encode($params);
$url = $this->baseURL . 'message';
return $this->post($url, $body);
}
/**
* 查询发送记录
*
* @param string $job_id 发送任务返回的 id
* @param string $message_id 单条短信发送接口返回的 id
* @param string $mobile 接收短信的手机号码
* @param string $status sending: 发送中success: 发送成功failed: 发送失败waiting: 等待发送
* @param string $template_id 模版 id
* @param string $type marketing:营销notification:通知verification:验证码voice:语音
* @param string $start 开始时间timestamp例如: 1563280448
* @param int $end 结束时间timestamp例如: 1563280471
* @param int $page 页码,默认为 1
* @param int $page_size 每页返回的数据条数默认20最大200
* @return array
* @link https://developer.qiniu.com/sms/api/5852/query-send-sms
*/
public function querySendSms(
$job_id = null,
$message_id = null,
$mobile = null,
$status = null,
$template_id = null,
$type = null,
$start = null,
$end = null,
$page = 1,
$page_size = 20
) {
$query = array();
\Qiniu\setWithoutEmpty($query, 'job_id', $job_id);
\Qiniu\setWithoutEmpty($query, 'message_id', $message_id);
\Qiniu\setWithoutEmpty($query, 'mobile', $mobile);
\Qiniu\setWithoutEmpty($query, 'status', $status);
\Qiniu\setWithoutEmpty($query, 'template_id', $template_id);
\Qiniu\setWithoutEmpty($query, 'type', $type);
\Qiniu\setWithoutEmpty($query, 'start', $start);
\Qiniu\setWithoutEmpty($query, 'end', $end);
\Qiniu\setWithoutEmpty($query, 'page', $page);
\Qiniu\setWithoutEmpty($query, 'page_size', $page_size);
$url = $this->baseURL . 'messages?' . http_build_query($query);
return $this->get($url);
}
public function imgToBase64($img_file)
{
$img_base64 = '';
if (file_exists($img_file)) {
$app_img_file = $img_file; // 图片路径
$img_info = getimagesize($app_img_file); // 取得图片的大小,类型等
$fp = fopen($app_img_file, "r"); // 图片是否可读权限
if ($fp) {
$filesize = filesize($app_img_file);
if ($filesize > 5 * 1024 * 1024) {
die("pic size < 5M !");
}
$img_type = null;
$content = fread($fp, $filesize);
$file_content = chunk_split(base64_encode($content)); // base64编码
switch ($img_info[2]) { //判读图片类型
case 1:
$img_type = 'gif';
break;
case 2:
$img_type = 'jpg';
break;
case 3:
$img_type = 'png';
break;
}
//合成图片的base64编码
$img_base64 = 'data:image/' . $img_type . ';base64,' . $file_content;
}
fclose($fp);
}
return $img_base64;
}
private function get($url, $contentType = 'application/x-www-form-urlencoded')
{
$headers = $this->auth->authorizationV2($url, "GET", null, $contentType);
$headers['Content-Type'] = $contentType;
$ret = Client::get($url, $headers);
if (!$ret->ok()) {
return array(null, new Error($url, $ret));
}
return array($ret->json(), null);
}
private function delete($url, $contentType = 'application/json')
{
$headers = $this->auth->authorizationV2($url, "DELETE", null, $contentType);
$headers['Content-Type'] = $contentType;
$ret = Client::delete($url, $headers);
if (!$ret->ok()) {
return array(null, new Error($url, $ret));
}
return array($ret->json(), null);
}
private function post($url, $body, $contentType = 'application/json')
{
$headers = $this->auth->authorizationV2($url, "POST", $body, $contentType);
$headers['Content-Type'] = $contentType;
$ret = Client::post($url, $body, $headers);
if (!$ret->ok()) {
return array(null, new Error($url, $ret));
}
$r = ($ret->body === null) ? array() : $ret->json();
return array($r, null);
}
private function PUT($url, $body, $contentType = 'application/json')
{
$headers = $this->auth->authorizationV2($url, "PUT", $body, $contentType);
$headers['Content-Type'] = $contentType;
$ret = Client::put($url, $body, $headers);
if (!$ret->ok()) {
return array(null, new Error($url, $ret));
}
$r = ($ret->body === null) ? array() : $ret->json();
return array($r, null);
}
}

View File

@@ -0,0 +1,123 @@
<?php
namespace Qiniu\Storage;
use Qiniu\Auth;
use Qiniu\Config;
use Qiniu\Zone;
use Qiniu\Http\Client;
use Qiniu\Http\Error;
/**
* 主要涉及了内容审核接口的实现,具体的接口规格可以参考
*
* @link https://developer.qiniu.com/censor/api/5620/video-censor
*/
final class ArgusManager
{
private $auth;
private $config;
public function __construct(Auth $auth, Config $config = null)
{
$this->auth = $auth;
if ($config == null) {
$this->config = new Config();
} else {
$this->config = $config;
}
}
/**
* 视频审核
*
* @param string $body body信息
*
* @return array 成功返回NULL失败返回对象Qiniu\Http\Error
* @link https://developer.qiniu.com/censor/api/5620/video-censor
*/
public function censorVideo($body)
{
$path = '/v3/video/censor';
return $this->arPost($path, $body);
}
/**
* 图片审核
*
* @param string $body
*
* @return array 成功返回NULL失败返回对象Qiniu\Http\Error
* @link https://developer.qiniu.com/censor/api/5588/image-censor
*/
public function censorImage($body)
{
$path = '/v3/image/censor';
return $this->arPost($path, $body);
}
/**
* 查询视频审核结果
*
* @param string $jobid 任务ID
* @return array
* @link https://developer.qiniu.com/censor/api/5620/video-censor
*/
public function censorStatus($jobid)
{
$scheme = "http://";
if ($this->config->useHTTPS === true) {
$scheme = "https://";
}
$url = $scheme . Config::ARGUS_HOST . "/v3/jobs/video/$jobid";
$response = $this->get($url);
if (!$response->ok()) {
print("statusCode: " . $response->statusCode);
return array(null, new Error($url, $response));
}
return array($response->json(), null);
}
private function getArHost()
{
$scheme = "http://";
if ($this->config->useHTTPS === true) {
$scheme = "https://";
}
return $scheme . Config::ARGUS_HOST;
}
private function arPost($path, $body = null)
{
$url = $this->getArHost() . $path;
return $this->post($url, $body);
}
private function get($url)
{
$headers = $this->auth->authorizationV2($url, 'GET');
return Client::get($url, $headers);
}
private function post($url, $body)
{
$headers = $this->auth->authorizationV2($url, 'POST', $body, 'application/json');
$headers['Content-Type'] = 'application/json';
$ret = Client::post($url, $body, $headers);
if (!$ret->ok()) {
print("statusCode: " . $ret->statusCode);
return array(null, new Error($url, $ret));
}
$r = ($ret->body === null) ? array() : $ret->json();
if (strstr($url, "video")) {
$jobid = $r['job'];
return array($jobid, null);
}
return array($r, null);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,140 @@
<?php
namespace Qiniu\Storage;
use Qiniu\Http\Error;
use Qiniu\Http\Client;
final class FormUploader
{
/**
* 上传二进制流到七牛, 内部使用
*
* @param string $upToken 上传凭证
* @param string $key 上传文件名
* @param string $data 上传二进制流
* @param string $config 上传配置
* @param string $params 自定义变量,规格参考
* https://developer.qiniu.com/kodo/manual/1235/vars#xvar
* @param string $mime 上传数据的mimeType
*
* @param string $fname
*
* @return array 包含已上传文件的信息,类似:
* [
* "hash" => "<Hash string>",
* "key" => "<Key string>"
* ]
*/
public static function put(
$upToken,
$key,
$data,
$config,
$params,
$mime,
$fname
) {
$fields = array('token' => $upToken);
if ($key === null) {
} else {
$fields['key'] = $key;
}
//enable crc32 check by default
$fields['crc32'] = \Qiniu\crc32_data($data);
if ($params) {
foreach ($params as $k => $v) {
$fields[$k] = $v;
}
}
list($accessKey, $bucket, $err) = \Qiniu\explodeUpToken($upToken);
if ($err != null) {
return array(null, $err);
}
$upHost = $config->getUpHost($accessKey, $bucket);
$response = Client::multipartPost($upHost, $fields, 'file', $fname, $data, $mime);
if (!$response->ok()) {
return array(null, new Error($upHost, $response));
}
return array($response->json(), null);
}
/**
* 上传文件到七牛,内部使用
*
* @param string $upToken 上传凭证
* @param string $key 上传文件名
* @param string $filePath 上传文件的路径
* @param string $config 上传配置
* @param string $params 自定义变量,规格参考
* https://developer.qiniu.com/kodo/manual/1235/vars#xvar
* @param string $mime 上传数据的mimeType
*
* @return array 包含已上传文件的信息,类似:
* [
* "hash" => "<Hash string>",
* "key" => "<Key string>"
* ]
*/
public static function putFile(
$upToken,
$key,
$filePath,
$config,
$params,
$mime
) {
$fields = array('token' => $upToken, 'file' => self::createFile($filePath, $mime));
if ($key !== null) {
$fields['key'] = $key;
}
$fields['crc32'] = \Qiniu\crc32_file($filePath);
if ($params) {
foreach ($params as $k => $v) {
$fields[$k] = $v;
}
}
$fields['key'] = $key;
$headers = array('Content-Type' => 'multipart/form-data');
list($accessKey, $bucket, $err) = \Qiniu\explodeUpToken($upToken);
if ($err != null) {
return array(null, $err);
}
$upHost = $config->getUpHost($accessKey, $bucket);
$response = Client::post($upHost, $fields, $headers);
if (!$response->ok()) {
return array(null, new Error($upHost, $response));
}
return array($response->json(), null);
}
private static function createFile($filename, $mime)
{
// PHP 5.5 introduced a CurlFile object that deprecates the old @filename syntax
// See: https://wiki.php.net/rfc/curl-file-upload
if (function_exists('curl_file_create')) {
return curl_file_create($filename, $mime);
}
// Use the old style if using an older version of PHP
$value = "@{$filename}";
if (!empty($mime)) {
$value .= ';type=' . $mime;
}
return $value;
}
}

View File

@@ -0,0 +1,171 @@
<?php
namespace Qiniu\Storage;
use Qiniu\Config;
use Qiniu\Http\Client;
use Qiniu\Http\Error;
/**
* 断点续上传类, 该类主要实现了断点续上传中的分块上传,
* 以及相应地创建块和创建文件过程.
*
* @link http://developer.qiniu.com/docs/v6/api/reference/up/mkblk.html
* @link http://developer.qiniu.com/docs/v6/api/reference/up/mkfile.html
*/
final class ResumeUploader
{
private $upToken;
private $key;
private $inputStream;
private $size;
private $params;
private $mime;
private $contexts;
private $host;
private $currentUrl;
private $config;
/**
* 上传二进制流到七牛
*
* @param string $upToken 上传凭证
* @param string $key 上传文件名
* @param string $inputStream 上传二进制流
* @param string $size 上传流的大小
* @param string $params 自定义变量
* @param string $mime 上传数据的mimeType
* @param string $config
*
* @link http://developer.qiniu.com/docs/v6/api/overview/up/response/vars.html#xvar
*/
public function __construct(
$upToken,
$key,
$inputStream,
$size,
$params,
$mime,
$config
) {
$this->upToken = $upToken;
$this->key = $key;
$this->inputStream = $inputStream;
$this->size = $size;
$this->params = $params;
$this->mime = $mime;
$this->contexts = array();
$this->config = $config;
list($accessKey, $bucket, $err) = \Qiniu\explodeUpToken($upToken);
if ($err != null) {
return array(null, $err);
}
$upHost = $config->getUpHost($accessKey, $bucket);
if ($err != null) {
throw new \Exception($err->message(), 1);
}
$this->host = $upHost;
}
/**
* 上传操作
*/
public function upload($fname)
{
$uploaded = 0;
while ($uploaded < $this->size) {
$blockSize = $this->blockSize($uploaded);
$data = fread($this->inputStream, $blockSize);
if ($data === false) {
throw new \Exception("file read failed", 1);
}
$crc = \Qiniu\crc32_data($data);
$response = $this->makeBlock($data, $blockSize);
$ret = null;
if ($response->ok() && $response->json() != null) {
$ret = $response->json();
}
if ($response->statusCode < 0) {
list($accessKey, $bucket, $err) = \Qiniu\explodeUpToken($this->upToken);
if ($err != null) {
return array(null, $err);
}
$upHostBackup = $this->config->getUpBackupHost($accessKey, $bucket);
$this->host = $upHostBackup;
}
if ($response->needRetry() || !isset($ret['crc32']) || $crc != $ret['crc32']) {
$response = $this->makeBlock($data, $blockSize);
$ret = $response->json();
}
if (!$response->ok() || !isset($ret['crc32']) || $crc != $ret['crc32']) {
return array(null, new Error($this->currentUrl, $response));
}
array_push($this->contexts, $ret['ctx']);
$uploaded += $blockSize;
}
return $this->makeFile($fname);
}
/**
* 创建块
*/
private function makeBlock($block, $blockSize)
{
$url = $this->host . '/mkblk/' . $blockSize;
return $this->post($url, $block);
}
private function fileUrl($fname)
{
$url = $this->host . '/mkfile/' . $this->size;
$url .= '/mimeType/' . \Qiniu\base64_urlSafeEncode($this->mime);
if ($this->key != null) {
$url .= '/key/' . \Qiniu\base64_urlSafeEncode($this->key);
}
$url .= '/fname/' . \Qiniu\base64_urlSafeEncode($fname);
if (!empty($this->params)) {
foreach ($this->params as $key => $value) {
$val = \Qiniu\base64_urlSafeEncode($value);
$url .= "/$key/$val";
}
}
return $url;
}
/**
* 创建文件
*/
private function makeFile($fname)
{
$url = $this->fileUrl($fname);
$body = implode(',', $this->contexts);
$response = $this->post($url, $body);
if ($response->needRetry()) {
$response = $this->post($url, $body);
}
if (!$response->ok()) {
return array(null, new Error($this->currentUrl, $response));
}
return array($response->json(), null);
}
private function post($url, $data)
{
$this->currentUrl = $url;
$headers = array('Authorization' => 'UpToken ' . $this->upToken);
return Client::post($url, $data, $headers);
}
private function blockSize($uploaded)
{
if ($this->size < $uploaded + Config::BLOCK_SIZE) {
return $this->size - $uploaded;
}
return Config::BLOCK_SIZE;
}
}

View File

@@ -0,0 +1,144 @@
<?php
namespace Qiniu\Storage;
use Qiniu\Config;
use Qiniu\Http\HttpClient;
use Qiniu\Storage\ResumeUploader;
use Qiniu\Storage\FormUploader;
/**
* 主要涉及了资源上传接口的实现
*
* @link http://developer.qiniu.com/docs/v6/api/reference/up/
*/
final class UploadManager
{
private $config;
public function __construct(Config $config = null)
{
if ($config === null) {
$config = new Config();
}
$this->config = $config;
}
/**
* 上传二进制流到七牛
*
* @param $upToken 上传凭证
* @param $key 上传文件名
* @param $data 上传二进制流
* @param $params 自定义变量,规格参考
* http://developer.qiniu.com/docs/v6/api/overview/up/response/vars.html#xvar
* @param $mime 上传数据的mimeType
* @param $checkCrc 是否校验crc32
*
* @return array 包含已上传文件的信息,类似:
* [
* "hash" => "<Hash string>",
* "key" => "<Key string>"
* ]
*/
public function put(
$upToken,
$key,
$data,
$params = null,
$mime = 'application/octet-stream',
$fname = "default_filename"
) {
$params = self::trimParams($params);
return FormUploader::put(
$upToken,
$key,
$data,
$this->config,
$params,
$mime,
$fname
);
}
/**
* 上传文件到七牛
*
* @param $upToken 上传凭证
* @param $key 上传文件名
* @param $filePath 上传文件的路径
* @param $params 自定义变量,规格参考
* http://developer.qiniu.com/docs/v6/api/overview/up/response/vars.html#xvar
* @param $mime 上传数据的mimeType
* @param $checkCrc 是否校验crc32
*
* @return array 包含已上传文件的信息,类似:
* [
* "hash" => "<Hash string>",
* "key" => "<Key string>"
* ]
*/
public function putFile(
$upToken,
$key,
$filePath,
$params = null,
$mime = 'application/octet-stream',
$checkCrc = false
) {
$file = fopen($filePath, 'rb');
if ($file === false) {
throw new \Exception("file can not open", 1);
}
$params = self::trimParams($params);
$stat = fstat($file);
$size = $stat['size'];
if ($size <= Config::BLOCK_SIZE) {
$data = fread($file, $size);
fclose($file);
if ($data === false) {
throw new \Exception("file can not read", 1);
}
return FormUploader::put(
$upToken,
$key,
$data,
$this->config,
$params,
$mime,
basename($filePath)
);
}
$up = new ResumeUploader(
$upToken,
$key,
$file,
$size,
$params,
$mime,
$this->config
);
$ret = $up->upload(basename($filePath));
fclose($file);
return $ret;
}
public static function trimParams($params)
{
if ($params === null) {
return null;
}
$ret = array();
foreach ($params as $k => $v) {
$pos1 = strpos($k, 'x:');
$pos2 = strpos($k, 'x-qn-meta-');
if (($pos1 === 0 || $pos2 === 0) && !empty($v)) {
$ret[$k] = $v;
}
}
return $ret;
}
}

47
vendor/qiniu/php-sdk/src/Qiniu/Zone.php vendored Normal file
View File

@@ -0,0 +1,47 @@
<?php
namespace Qiniu;
use Qiniu\Region;
class Zone extends Region
{
public static function zonez0()
{
return parent::regionHuadong();
}
public static function zonez1()
{
return parent::regionHuabei();
}
public static function zonez2()
{
return parent::regionHuanan();
}
public static function zoneAs0()
{
return parent::regionSingapore();
}
public static function zoneNa0()
{
return parent::regionNorthAmerica();
}
public static function qvmZonez0()
{
return parent::qvmRegionHuadong();
}
public static function qvmZonez1()
{
return parent::qvmRegionHuabei();
}
public static function queryZone($ak, $bucket)
{
return parent::queryRegion($ak, $bucket);
}
}

View File

@@ -0,0 +1,264 @@
<?php
namespace Qiniu;
use Qiniu\Config;
if (!defined('QINIU_FUNCTIONS_VERSION')) {
define('QINIU_FUNCTIONS_VERSION', Config::SDK_VER);
/**
* 计算文件的crc32检验码:
*
* @param $file string 待计算校验码的文件路径
*
* @return string 文件内容的crc32校验码
*/
function crc32_file($file)
{
$hash = hash_file('crc32b', $file);
$array = unpack('N', pack('H*', $hash));
return sprintf('%u', $array[1]);
}
/**
* 计算输入流的crc32检验码
*
* @param $data 待计算校验码的字符串
*
* @return string 输入字符串的crc32校验码
*/
function crc32_data($data)
{
$hash = hash('crc32b', $data);
$array = unpack('N', pack('H*', $hash));
return sprintf('%u', $array[1]);
}
/**
* 对提供的数据进行urlsafe的base64编码。
*
* @param string $data 待编码的数据,一般为字符串
*
* @return string 编码后的字符串
* @link http://developer.qiniu.com/docs/v6/api/overview/appendix.html#urlsafe-base64
*/
function base64_urlSafeEncode($data)
{
$find = array('+', '/');
$replace = array('-', '_');
return str_replace($find, $replace, base64_encode($data));
}
/**
* 对提供的urlsafe的base64编码的数据进行解码
*
* @param string $str 待解码的数据,一般为字符串
*
* @return string 解码后的字符串
*/
function base64_urlSafeDecode($str)
{
$find = array('-', '_');
$replace = array('+', '/');
return base64_decode(str_replace($find, $replace, $str));
}
/**
* Wrapper for JSON decode that implements error detection with helpful
* error messages.
*
* @param string $json JSON data to parse
* @param bool $assoc When true, returned objects will be converted
* into associative arrays.
* @param int $depth User specified recursion depth.
*
* @return mixed
* @throws \InvalidArgumentException if the JSON cannot be parsed.
* @link http://www.php.net/manual/en/function.json-decode.php
*/
function json_decode($json, $assoc = false, $depth = 512)
{
static $jsonErrors = array(
JSON_ERROR_DEPTH => 'JSON_ERROR_DEPTH - Maximum stack depth exceeded',
JSON_ERROR_STATE_MISMATCH => 'JSON_ERROR_STATE_MISMATCH - Underflow or the modes mismatch',
JSON_ERROR_CTRL_CHAR => 'JSON_ERROR_CTRL_CHAR - Unexpected control character found',
JSON_ERROR_SYNTAX => 'JSON_ERROR_SYNTAX - Syntax error, malformed JSON',
JSON_ERROR_UTF8 => 'JSON_ERROR_UTF8 - Malformed UTF-8 characters, possibly incorrectly encoded'
);
if (empty($json)) {
return null;
}
$data = \json_decode($json, $assoc, $depth);
if (JSON_ERROR_NONE !== json_last_error()) {
$last = json_last_error();
throw new \InvalidArgumentException(
'Unable to parse JSON data: '
. (isset($jsonErrors[$last])
? $jsonErrors[$last]
: 'Unknown error')
);
}
return $data;
}
/**
* 计算七牛API中的数据格式
*
* @param string $bucket 待操作的空间名
* @param string $key 待操作的文件名
*
* @return string 符合七牛API规格的数据格式
* @link http://developer.qiniu.com/docs/v6/api/reference/data-formats.html
*/
function entry($bucket, $key)
{
$en = $bucket;
if (!empty($key)) {
$en = $bucket . ':' . $key;
}
return base64_urlSafeEncode($en);
}
/**
* array 辅助方法无值时不set
*
* @param array $array 待操作array
* @param string $key key
* @param string $value value 为null时 不设置
*
* @return array 原来的array便于连续操作
*/
function setWithoutEmpty(&$array, $key, $value)
{
if (!empty($value)) {
$array[$key] = $value;
}
return $array;
}
/**
* 缩略图链接拼接
*
* @param string $url 图片链接
* @param int $mode 缩略模式
* @param int $width 宽度
* @param int $height 长度
* @param string $format 输出类型
* @param int $quality 图片质量
* @param int $interlace 是否支持渐进显示
* @param int $ignoreError 忽略结果
* @return string
* @link http://developer.qiniu.com/code/v6/api/kodo-api/image/imageview2.html
* @author Sherlock Ren <sherlock_ren@icloud.com>
*/
function thumbnail(
$url,
$mode,
$width,
$height,
$format = null,
$quality = null,
$interlace = null,
$ignoreError = 1
) {
static $imageUrlBuilder = null;
if (is_null($imageUrlBuilder)) {
$imageUrlBuilder = new \Qiniu\Processing\ImageUrlBuilder;
}
return call_user_func_array(array($imageUrlBuilder, 'thumbnail'), func_get_args());
}
/**
* 图片水印
*
* @param string $url 图片链接
* @param string $image 水印图片链接
* @param numeric $dissolve 透明度
* @param string $gravity 水印位置
* @param numeric $dx 横轴边距
* @param numeric $dy 纵轴边距
* @param numeric $watermarkScale 自适应原图的短边比例
* @link http://developer.qiniu.com/code/v6/api/kodo-api/image/watermark.html
* @return string
* @author Sherlock Ren <sherlock_ren@icloud.com>
*/
function waterImg(
$url,
$image,
$dissolve = 100,
$gravity = 'SouthEast',
$dx = null,
$dy = null,
$watermarkScale = null
) {
static $imageUrlBuilder = null;
if (is_null($imageUrlBuilder)) {
$imageUrlBuilder = new \Qiniu\Processing\ImageUrlBuilder;
}
return call_user_func_array(array($imageUrlBuilder, 'waterImg'), func_get_args());
}
/**
* 文字水印
*
* @param string $url 图片链接
* @param string $text 文字
* @param string $font 文字字体
* @param string $fontSize 文字字号
* @param string $fontColor 文字颜色
* @param numeric $dissolve 透明度
* @param string $gravity 水印位置
* @param numeric $dx 横轴边距
* @param numeric $dy 纵轴边距
* @link http://developer.qiniu.com/code/v6/api/kodo-api/image/watermark.html#text-watermark
* @return string
* @author Sherlock Ren <sherlock_ren@icloud.com>
*/
function waterText(
$url,
$text,
$font = '黑体',
$fontSize = 0,
$fontColor = null,
$dissolve = 100,
$gravity = 'SouthEast',
$dx = null,
$dy = null
) {
static $imageUrlBuilder = null;
if (is_null($imageUrlBuilder)) {
$imageUrlBuilder = new \Qiniu\Processing\ImageUrlBuilder;
}
return call_user_func_array(array($imageUrlBuilder, 'waterText'), func_get_args());
}
/**
* 从uptoken解析accessKey和bucket
*
* @param $upToken
* @return array(ak,bucket,err=null)
*/
function explodeUpToken($upToken)
{
$items = explode(':', $upToken);
if (count($items) != 3) {
return array(null, null, "invalid uptoken");
}
$accessKey = $items[0];
$putPolicy = json_decode(base64_urlSafeDecode($items[2]));
$scope = $putPolicy->scope;
$scopeItems = explode(':', $scope);
$bucket = $scopeItems[0];
return array($accessKey, $bucket, null);
}
}