diff --git a/app/admin/controller/Config.php b/app/admin/controller/Config.php
index 69e468609..d8757e731 100644
--- a/app/admin/controller/Config.php
+++ b/app/admin/controller/Config.php
@@ -19,6 +19,9 @@ use think\admin\Controller;
use think\admin\service\AdminService;
use think\admin\service\ModuleService;
use think\admin\service\SystemService;
+use think\admin\storage\AliossStorage;
+use think\admin\storage\QiniuStorage;
+use think\admin\storage\TxcosStorage;
/**
* 系统参数配置
@@ -34,33 +37,6 @@ class Config extends Controller
*/
protected $table = 'SystemConfig';
- /**
- * 阿里数据中心
- * @var array
- */
- protected $points = [
- 'oss-cn-hangzhou.aliyuncs.com' => '华东 1(杭州)',
- 'oss-cn-shanghai.aliyuncs.com' => '华东 2(上海)',
- 'oss-cn-qingdao.aliyuncs.com' => '华北 1(青岛)',
- 'oss-cn-beijing.aliyuncs.com' => '华北 2(北京)',
- 'oss-cn-zhangjiakou.aliyuncs.com' => '华北 3(张家口)',
- 'oss-cn-huhehaote.aliyuncs.com' => '华北 5(呼和浩特)',
- 'oss-cn-shenzhen.aliyuncs.com' => '华南 1(深圳)',
- 'oss-cn-chengdu.aliyuncs.com' => '西南 1(成都)',
- 'oss-cn-hongkong.aliyuncs.com' => '中国(香港)',
- 'oss-us-west-1.aliyuncs.com' => '美国西部 1(硅谷)',
- 'oss-us-east-1.aliyuncs.com' => '美国东部 1(弗吉尼亚)',
- 'oss-ap-southeast-1.aliyuncs.com' => '亚太东南 1(新加坡)',
- 'oss-ap-southeast-2.aliyuncs.com' => '亚太东南 2(悉尼)',
- 'oss-ap-southeast-3.aliyuncs.com' => '亚太东南 3(吉隆坡)',
- 'oss-ap-southeast-5.aliyuncs.com' => '亚太东南 5(雅加达)',
- 'oss-ap-northeast-1.aliyuncs.com' => '亚太东北 1(日本)',
- 'oss-ap-south-1.aliyuncs.com' => '亚太南部 1(孟买)',
- 'oss-eu-central-1.aliyuncs.com' => '欧洲中部 1(法兰克福)',
- 'oss-eu-west-1.aliyuncs.com' => '英国(伦敦)',
- 'oss-me-east-1.aliyuncs.com' => '中东东部 1(迪拜)',
- ];
-
/**
* 系统参数配置
* @auth true
@@ -114,6 +90,13 @@ class Config extends Controller
$this->_applyFormToken();
if ($this->request->isGet()) {
$this->type = input('type', 'local');
+ if ($this->type === 'alioss') {
+ $this->points = AliossStorage::region();
+ } elseif ($this->type === 'txcos') {
+ $this->points = TxcosStorage::region();
+ } elseif ($this->type === 'qiniu') {
+ $this->points = QiniuStorage::region();
+ }
$this->fetch("storage-{$this->type}");
} else {
$post = $this->request->post();
diff --git a/app/admin/controller/api/Upload.php b/app/admin/controller/api/Upload.php
index dc1564bf7..d990a9bdf 100644
--- a/app/admin/controller/api/Upload.php
+++ b/app/admin/controller/api/Upload.php
@@ -20,6 +20,7 @@ use think\admin\Storage;
use think\admin\storage\AliossStorage;
use think\admin\storage\LocalStorage;
use think\admin\storage\QiniuStorage;
+use think\admin\storage\TxcosStorage;
/**
* 文件上传接口
@@ -76,6 +77,15 @@ class Upload extends Controller
$data['signature'] = $token['signature'];
$data['OSSAccessKeyId'] = $token['keyid'];
$data['server'] = AliossStorage::instance()->upload();
+ } elseif ('txcos' === $data['uptype']) {
+ $token = TxcosStorage::instance()->buildUploadToken($data['xkey'], 3600, $this->name);
+ $data['url'] = $token['siteurl'];
+ $data['q-ak'] = $token['q-ak'];
+ $data['policy'] = $token['policy'];
+ $data['q-key-time'] = $token['q-key-time'];
+ $data['q-signature'] = $token['d-signature'];
+ $data['q-sign-algorithm'] = $token['q-sign-algorithm'];
+ $data['server'] = TxcosStorage::instance()->upload();
}
$this->success('获取授权参数', $data, 404);
}
@@ -139,7 +149,7 @@ class Upload extends Controller
private function getType()
{
$this->uptype = strtolower(input('uptype', ''));
- if (!in_array($this->uptype, ['local', 'qiniu', 'alioss'])) {
+ if (!in_array($this->uptype, ['local', 'qiniu', 'alioss', 'txcos'])) {
$this->uptype = strtolower(sysconf('storage.type'));
}
return strtolower($this->uptype);
diff --git a/app/admin/view/api/upload.js b/app/admin/view/api/upload.js
index e6de1c9a0..8a3514e78 100644
--- a/app/admin/view/api/upload.js
+++ b/app/admin/view/api/upload.js
@@ -39,6 +39,14 @@ define(['md5'], function (SparkMD5, allowMime) {
option.uploader.config.data.OSSAccessKeyId = ret.data.OSSAccessKeyId;
option.uploader.config.data.success_action_status = 200;
option.uploader.config.data['Content-Disposition'] = 'inline;filename=' + encodeURIComponent(file.name);
+ } else if (ret.data.uptype === 'txcos') {
+ option.uploader.config.data.policy = ret.data.policy;
+ option.uploader.config.data['q-ak'] = ret.data['q-ak'];
+ option.uploader.config.data['q-key-time'] = ret.data['q-key-time'];
+ option.uploader.config.data['q-signature'] = ret.data['q-signature'];
+ option.uploader.config.data['q-sign-algorithm'] = ret.data['q-sign-algorithm'];
+ option.uploader.config.data.success_action_status = 200;
+ option.uploader.config.data['Content-Disposition'] = 'inline;filename=' + encodeURIComponent(file.name);
}
object.upload(file.index, file);
} else if (parseInt(ret.code) === 200) {
diff --git a/app/admin/view/config/index.html b/app/admin/view/config/index.html
index 9428eb7e6..d4bd5d9d2 100644
--- a/app/admin/view/config/index.html
+++ b/app/admin/view/config/index.html
@@ -39,7 +39,7 @@
- {foreach ['local' => '本地服务器存储','qiniu' => '七牛云对象存储','alioss' => '阿里云OSS存储'] as $k => $v} {if sysconf('storage.type') eq $k}
+ {foreach ['local' => '本地服务器存储','qiniu' => '七牛云对象存储','alioss' => '阿里云OSS存储','txcos' => '腾讯云COS存储'] as $k => $v} {if sysconf('storage.type') eq $k}
{if auth('storage')}
{$v}{else}
{$v}{/if}
{else}
{if auth('storage')}
{$v}{else}
{$v}{/if}
@@ -49,6 +49,7 @@
本地服务器存储:文件直接上传到本地服务器的 `static/upload` 目录,不支持大文件上传,占用服务器磁盘空间,访问时消耗服务器带宽流量。
七牛云对象存储:文件直接上传到七牛云存储空间,支持大文件上传,不占用服务器空间及服务器带宽流量,支持 CDN 加速访问,访问量大时推荐使用。
阿里云OSS存储:文件直接上传到阿里云 OSS 存储空间,支持大文件上传,不占用服务器空间及服务器带宽流量,支持 CDN 加速访问,访问量大时推荐使用。
+
腾讯云COS存储:文件直接上传到腾讯云 COS 存储空间,支持大文件上传,不占用服务器空间及服务器带宽流量,支持 CDN 加速访问,访问量大时推荐使用。
diff --git a/app/admin/view/config/storage-0.html b/app/admin/view/config/storage-0.html
index 3ec770b73..bb996ea36 100644
--- a/app/admin/view/config/storage-0.html
+++ b/app/admin/view/config/storage-0.html
@@ -3,6 +3,7 @@
链接类型
LinkType
@@ -34,9 +35,9 @@
阿里云OSS存储空间所在区域,需要严格对应储存所在区域才能上传文件
@@ -49,7 +50,7 @@
@@ -59,7 +60,7 @@
diff --git a/app/admin/view/config/storage-local.html b/app/admin/view/config/storage-local.html
index fb1bc1903..891dd5144 100644
--- a/app/admin/view/config/storage-local.html
+++ b/app/admin/view/config/storage-local.html
@@ -13,16 +13,17 @@
访问协议
Protocol
diff --git a/app/admin/view/config/storage-qiniu.html b/app/admin/view/config/storage-qiniu.html
index 1c98f5490..85de490e6 100644
--- a/app/admin/view/config/storage-qiniu.html
+++ b/app/admin/view/config/storage-qiniu.html
@@ -13,16 +13,17 @@
访问协议
Protocol
diff --git a/app/admin/view/config/storage-txcos.html b/app/admin/view/config/storage-txcos.html
new file mode 100644
index 000000000..ee82d88b7
--- /dev/null
+++ b/app/admin/view/config/storage-txcos.html
@@ -0,0 +1,108 @@
+
\ No newline at end of file
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index fa15fcff2..d7f33aecb 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -893,12 +893,12 @@
"source": {
"type": "git",
"url": "https://github.com/zoujingli/ThinkLibrary.git",
- "reference": "213b606ab9906914296f475324538b93c18406dd"
+ "reference": "be1ddab224ab14d814ae120eebfb53b25808bbfa"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/zoujingli/ThinkLibrary/zipball/213b606ab9906914296f475324538b93c18406dd",
- "reference": "213b606ab9906914296f475324538b93c18406dd",
+ "url": "https://api.github.com/repos/zoujingli/ThinkLibrary/zipball/be1ddab224ab14d814ae120eebfb53b25808bbfa",
+ "reference": "be1ddab224ab14d814ae120eebfb53b25808bbfa",
"shasum": "",
"mirrors": [
{
@@ -915,7 +915,7 @@
"ext-mbstring": "*",
"topthink/framework": "^6.0"
},
- "time": "2020-10-15T01:37:16+00:00",
+ "time": "2020-10-15T03:06:04+00:00",
"type": "library",
"extra": {
"think": {
diff --git a/vendor/services.php b/vendor/services.php
index aa3a79718..40723dae5 100644
--- a/vendor/services.php
+++ b/vendor/services.php
@@ -1,5 +1,5 @@
'think\\admin\\Library',
diff --git a/vendor/zoujingli/think-library/src/storage/AliossStorage.php b/vendor/zoujingli/think-library/src/storage/AliossStorage.php
index 076f0bab3..a5038abe0 100644
--- a/vendor/zoujingli/think-library/src/storage/AliossStorage.php
+++ b/vendor/zoujingli/think-library/src/storage/AliossStorage.php
@@ -201,8 +201,8 @@ class AliossStorage extends Storage
*/
public function upload(): string
{
- $http = $this->app->request->isSsl() ? 'https' : 'http';
- return "{$http}://{$this->bucket}.{$this->point}";
+ $protocol = $this->app->request->isSsl() ? 'https' : 'http';
+ return "{$protocol}://{$this->bucket}.{$this->point}";
}
/**
@@ -219,8 +219,8 @@ class AliossStorage extends Storage
'conditions' => [['content-length-range', 0, 1048576000]],
'expiration' => date('Y-m-d\TH:i:s.000\Z', time() + $expires),
])),
- 'siteurl' => $this->url($name, false, $attname),
'keyid' => $this->accessKey,
+ 'siteurl' => $this->url($name, false, $attname),
];
$data['signature'] = base64_encode(hash_hmac('sha1', $data['policy'], $this->secretKey, true));
return $data;
@@ -254,4 +254,34 @@ class AliossStorage extends Storage
return array_values($header);
}
+ /**
+ * 阿里云OSS存储区域
+ * @return array
+ */
+ public static function region()
+ {
+ return [
+ 'oss-cn-hangzhou.aliyuncs.com' => '华东 1(杭州)',
+ 'oss-cn-shanghai.aliyuncs.com' => '华东 2(上海)',
+ 'oss-cn-qingdao.aliyuncs.com' => '华北 1(青岛)',
+ 'oss-cn-beijing.aliyuncs.com' => '华北 2(北京)',
+ 'oss-cn-zhangjiakou.aliyuncs.com' => '华北 3(张家口)',
+ 'oss-cn-huhehaote.aliyuncs.com' => '华北 5(呼和浩特)',
+ 'oss-cn-shenzhen.aliyuncs.com' => '华南 1(深圳)',
+ 'oss-cn-chengdu.aliyuncs.com' => '西南 1(成都)',
+ 'oss-cn-hongkong.aliyuncs.com' => '中国(香港)',
+ 'oss-us-west-1.aliyuncs.com' => '美国西部 1(硅谷)',
+ 'oss-us-east-1.aliyuncs.com' => '美国东部 1(弗吉尼亚)',
+ 'oss-ap-southeast-1.aliyuncs.com' => '亚太东南 1(新加坡)',
+ 'oss-ap-southeast-2.aliyuncs.com' => '亚太东南 2(悉尼)',
+ 'oss-ap-southeast-3.aliyuncs.com' => '亚太东南 3(吉隆坡)',
+ 'oss-ap-southeast-5.aliyuncs.com' => '亚太东南 5(雅加达)',
+ 'oss-ap-northeast-1.aliyuncs.com' => '亚太东北 1(日本)',
+ 'oss-ap-south-1.aliyuncs.com' => '亚太南部 1(孟买)',
+ 'oss-eu-central-1.aliyuncs.com' => '欧洲中部 1(法兰克福)',
+ 'oss-eu-west-1.aliyuncs.com' => '英国(伦敦)',
+ 'oss-me-east-1.aliyuncs.com' => '中东东部 1(迪拜)',
+ ];
+ }
+
}
\ No newline at end of file
diff --git a/vendor/zoujingli/think-library/src/storage/QiniuStorage.php b/vendor/zoujingli/think-library/src/storage/QiniuStorage.php
index 2da326858..87eff5c51 100644
--- a/vendor/zoujingli/think-library/src/storage/QiniuStorage.php
+++ b/vendor/zoujingli/think-library/src/storage/QiniuStorage.php
@@ -232,4 +232,19 @@ class QiniuStorage extends Storage
$sign = hash_hmac('sha1', "/{$type}/{$entry}\n", $this->secretKey, true);
return [$entry, "{$this->accessKey}:{$this->safeBase64($sign)}"];
}
+
+ /**
+ * 七牛云对象存储区域
+ * @return array
+ */
+ public static function region()
+ {
+ return [
+ 'up.qiniup.com' => '华东',
+ 'up-z1.qiniup.com' => '华北',
+ 'up-z2.qiniup.com' => '华南',
+ 'up-na0.qiniup.com' => '北美',
+ 'up-as0.qiniup.com' => '东南亚',
+ ];
+ }
}
\ No newline at end of file
diff --git a/vendor/zoujingli/think-library/src/storage/TxcosStorage.php b/vendor/zoujingli/think-library/src/storage/TxcosStorage.php
index 644a05c25..3a5242abc 100644
--- a/vendor/zoujingli/think-library/src/storage/TxcosStorage.php
+++ b/vendor/zoujingli/think-library/src/storage/TxcosStorage.php
@@ -20,6 +20,12 @@ class TxcosStorage extends Storage
*/
private $point;
+ /**
+ * 账号 AppID
+ * @var string
+ */
+ private $appid;
+
/**
* 存储空间名称
* @var string
@@ -48,6 +54,7 @@ class TxcosStorage extends Storage
protected function initialize()
{
// 读取配置文件
+ $this->appid = sysconf('storage.txcos_appid');
$this->point = sysconf('storage.txcos_point');
$this->bucket = sysconf('storage.txcos_bucket');
$this->secretId = sysconf('storage.txcos_secret_id');
@@ -92,11 +99,11 @@ class TxcosStorage extends Storage
$data['q-ak'] = $token['q-ak'];
$data['q-key-time'] = $token['q-key-time'];
$data['q-signature'] = $token['d-signature'];
- $data['success_action_status'] = '200';
if (is_string($attname) && strlen($attname) > 0) {
$filename = urlencode($attname);
$data['Content-Disposition'] = "inline;filename={$filename}";
}
+ $data['success_action_status'] = '200';
$file = ['field' => 'file', 'name' => $name, 'content' => $file];
if (is_numeric(stripos(HttpExtend::submit($this->upload(), $data, $file), '200 OK'))) {
return ['file' => $this->path($name, $safe), 'url' => $this->url($name, $safe, $attname), 'key' => $name];
@@ -125,7 +132,7 @@ class TxcosStorage extends Storage
public function del(string $name, bool $safe = false)
{
[$file] = explode('?', $name);
- $result = HttpExtend::request('DELETE', "http://{$this->bucket}.{$this->point}/{$file}", [
+ $result = HttpExtend::request('DELETE', "http://{$this->bucket}-{$this->appid}.{$this->point}/{$file}", [
'returnHeader' => true, 'headers' => $this->headerSign('DELETE', $file),
]);
return is_numeric(stripos($result, '204 No Content'));
@@ -140,7 +147,7 @@ class TxcosStorage extends Storage
public function has(string $name, bool $safe = false)
{
$file = $this->delSuffix($name);
- $result = HttpExtend::request('HEAD', "http://{$this->bucket}.{$this->point}/{$file}", [
+ $result = HttpExtend::request('HEAD', "http://{$this->bucket}-{$this->appid}.{$this->point}/{$file}", [
'returnHeader' => true, 'headers' => $this->headerSign('HEAD', $name),
]);
return is_numeric(stripos($result, 'HTTP/1.1 200 OK'));
@@ -190,8 +197,8 @@ class TxcosStorage extends Storage
*/
public function upload(): string
{
- $http = $this->app->request->isSsl() ? 'https' : 'http';
- return "{$http}://{$this->bucket}.{$this->point}";
+ $protocol = $this->app->request->isSsl() ? 'https' : 'http';
+ return "{$protocol}://{$this->bucket}-{$this->appid}.{$this->point}";
}
/**
@@ -209,23 +216,16 @@ class TxcosStorage extends Storage
$siteurl = $this->url($name, false, $attname);
$policy = json_encode([
'expiration' => date('Y-m-d\TH:i:s.000\Z', $endTimestamp),
- 'conditions' => [
- ['q-sign-algorithm' => 'sha1'],
- ['q-ak' => $this->secretId],
- ['q-sign-time' => $keyTime]
- ],
+ 'conditions' => [['q-sign-algorithm' => 'sha1'], ['q-ak' => $this->secretId], ['q-sign-time' => $keyTime]],
]);
- $data = [
+ return [
'policy' => base64_encode($policy),
'q-sign-algorithm' => 'sha1',
'q-ak' => $this->secretId,
'q-key-time' => $keyTime,
- 'siteurl' => $siteurl
+ 'q-signature' => hash_hmac('sha1', sha1($policy), hash_hmac('sha1', $keyTime, $this->secretKey)),
+ 'siteurl' => $siteurl,
];
- $signKey = hash_hmac('sha1', $keyTime, $this->secretKey);
- $stringToSign = sha1($policy);
- $data['q-signature'] = hash_hmac('sha1', $stringToSign, $signKey);
- return $data;
}
/**
@@ -237,33 +237,33 @@ class TxcosStorage extends Storage
*/
private function headerSign(string $method, string $soruce, array $header = []): array
{
- // 1.生成KeyTime
+ // 1.生成 KeyTime
$startTimestamp = time();
$endTimestamp = $startTimestamp + 3600;
$keyTime = "{$startTimestamp};{$endTimestamp}";
// 2.生成 SignKey
$signKey = hash_hmac('sha1', $keyTime, $this->secretKey);
- // 3.生成UrlParamList,HttpParameters
- list($parse_url, $urlParamList, $httpParameters) = [parse_url($soruce), '', ''];
+ // 3.生成 UrlParamList, HttpParameters
+ [$parse_url, $urlParamList, $httpParameters] = [parse_url($soruce), '', ''];
if (!empty($parse_url['query'])) {
parse_str($parse_url['query'], $params);
uksort($params, 'strnatcasecmp');
$urlParamList = join(';', array_keys($params));
$httpParameters = http_build_query($params);
}
- // 4.生成HeaderList,HttpHeaders
- list($headerList, $httpHeaders) = ['', ''];
+ // 4.生成 HeaderList, HttpHeaders
+ [$headerList, $httpHeaders] = ['', ''];
if (!empty($header)) {
uksort($header, 'strnatcasecmp');
$headerList = join(';', array_keys($header));
$httpHeaders = http_build_query($header);
}
- // 5.生成HttpString
+ // 5.生成 HttpString
$httpString = strtolower($method) . "\n/{$parse_url['path']}\n{$httpParameters}\n{$httpHeaders}\n";
- // 6.生成StringToSign
+ // 6.生成 StringToSign
$httpStringSha1 = sha1($httpString);
$stringToSign = "sha1\n{$keyTime}\n{$httpStringSha1}\n";
- // 7.生成Signature
+ // 7.生成 Signature
$signature = hash_hmac('sha1', $stringToSign, $signKey);
// 8.生成签名
$signArray = [
@@ -273,11 +273,42 @@ class TxcosStorage extends Storage
'q-key-time' => $keyTime,
'q-header-list' => $headerList,
'q-url-param-list' => $urlParamList,
- 'q-signature' => $signature
+ 'q-signature' => $signature,
];
$header['Authorization'] = urldecode(http_build_query($signArray));
foreach ($header as $key => $value) $header[$key] = ucfirst($key) . ": {$value}";
return array_values($header);
}
+ /**
+ * 腾讯云COS存储区域
+ * @return array
+ */
+ public static function region()
+ {
+ return [
+ 'cos.ap-beijing-1.myqcloud.com' => '中国大陆 公有云地域 北京一区(已售罄)',
+ 'cos.ap-beijing.myqcloud.com' => '中国大陆 公有云地域 北京',
+ 'cos.ap-nanjing.myqcloud.com' => '中国大陆 公有云地域 南京',
+ 'cos.ap-shanghai.myqcloud.com' => '中国大陆 公有云地域 上海',
+ 'cos.ap-guangzhou.myqcloud.com' => '中国大陆 公有云地域 广州',
+ 'cos.ap-chengdu.myqcloud.com' => '中国大陆 公有云地域 成都',
+ 'cos.ap-chongqing.myqcloud.com' => '中国大陆 公有云地域 重庆',
+ 'cos.ap-shenzhen-fsi.myqcloud.com' => '中国大陆 金融云地域 深圳金融',
+ 'cos.ap-shanghai-fsi.myqcloud.com' => '中国大陆 金融云地域 上海金融',
+ 'cos.ap-beijing-fsi.myqcloud.com' => '中国大陆 金融云地域 北京金融',
+ 'cos.ap-hongkong.myqcloud.com' => '亚太地区 公有云地域 中国香港',
+ 'cos.ap-singapore.myqcloud.com' => '亚太地区 公有云地域 新加坡',
+ 'cos.ap-mumbai.myqcloud.com' => '亚太地区 公有云地域 孟买',
+ 'cos.ap-seoul.myqcloud.com' => '亚太地区 公有云地域 首尔',
+ 'cos.ap-bangkok.myqcloud.com' => '亚太地区 公有云地域 曼谷',
+ 'cos.ap-tokyo.myqcloud.com' => '亚太地区 公有云地域 东京',
+ 'cos.na-siliconvalley.myqcloud.com' => '北美地区 公有云地域 硅谷',
+ 'cos.na-ashburn.myqcloud.com' => '北美地区 公有云地域 弗吉尼亚',
+ 'cos.na-toronto.myqcloud.com' => '北美地区 公有云地域 多伦多',
+ 'cos.eu-frankfurt.myqcloud.com' => '欧洲地区 公有云地域 法兰克福',
+ 'cos.eu-moscow.myqcloud.com' => '欧洲地区 公有云地域 莫斯科 ',
+ ];
+ }
+
}
\ No newline at end of file