perf: 文件存储迁移到 filesystem

This commit is contained in:
daodao97
2020-10-15 17:14:03 +08:00
parent 1d993ace73
commit 01e9633e02
12 changed files with 611 additions and 76 deletions

View File

@@ -23,7 +23,7 @@
"hyperf/crontab": "~2.0.0", "hyperf/crontab": "~2.0.0",
"hyperf/database": "~2.0.0", "hyperf/database": "~2.0.0",
"hyperf/db-connection": "~2.0.0", "hyperf/db-connection": "~2.0.0",
"hyperf/filesystem": "~2.0.0", "hyperf/filesystem": "^2.0",
"hyperf/framework": "~2.0.0", "hyperf/framework": "~2.0.0",
"hyperf/guzzle": "~2.0.0", "hyperf/guzzle": "~2.0.0",
"hyperf/http-server": "~2.0.0", "hyperf/http-server": "~2.0.0",
@@ -36,6 +36,7 @@
"hyperf/snowflake": "~2.0.0", "hyperf/snowflake": "~2.0.0",
"hyperf/validation": "~2.0.0", "hyperf/validation": "~2.0.0",
"nette/php-generator": "^3.4", "nette/php-generator": "^3.4",
"xxtime/flysystem-aliyun-oss": "^1.5",
"yadakhov/insert-on-duplicate-key": "^1.2", "yadakhov/insert-on-duplicate-key": "^1.2",
"zoujingli/ip2region": "^1.0" "zoujingli/ip2region": "^1.0"
}, },

View File

@@ -14,6 +14,7 @@
* [远程脚手架](backend/remote_scaffold.md) * [远程脚手架](backend/remote_scaffold.md)
* [通用配置](backend/common-config.md) * [通用配置](backend/common-config.md)
* [辅助函数](backend/functions.md) * [辅助函数](backend/functions.md)
* [文件上传](backend/file.md)
* 业务组件 * 业务组件
* [业务组件介绍](backend/components/business/desc.md) * [业务组件介绍](backend/components/business/desc.md)
* [DevTools-开发者工具](backend/components/business/dev-tools.md) * [DevTools-开发者工具](backend/components/business/dev-tools.md)

37
docs/backend/file.md Normal file
View File

@@ -0,0 +1,37 @@
## 文件上传
文件的处理统一使用 `hyperf/filesystem`, 请先阅读其文档 [biu~~](https://hyperf.wiki/2.0/#/zh-cn/filesystem)
### 文件的上传
表单的控件中可以指定 `存储介质`, `可见性` 等.
```php
'form' => [
'avatar|用户头像' => [
'type' => 'image',
'rule' => 'string',
'readonly' => true,
'props' => [
'bucket' => 'aliyuncs', // 指定存储的storage, 可选详见 config/autoload/file.php storage
'private' => true, // 是否为私有
]
],
]
```
### 两个快捷方法
1. `move_local_file_to_filesystem($local_file_path, $save_file_path, $private = false, $bucket = 'aliyuncs', $update_when_exist = true)`
将本地文件通过 `filesystem` 指定的介质来存储
2. `filesystem_private_url($save_file_path, $timeout = 60, $bucket = 'aliyuncs')`
获取私有文件的临时访问链接
### 提示
如果存储方式为 `本地`, 我们 增加了 `file.storage.local.cdn` 这个配置项, 用于生成可用的访问链接.
如果使用的其他存储介质, 请记得安装相应扩展包.
!> 当前仅对 `本地`, `阿里云oss` 做了适配, 因为没有其他元的账号..., 如果您当前使用的存储介质(如: 腾讯云), 请反馈给我们, 如能提供测试账号验证下更好.

View File

@@ -52,9 +52,9 @@
#### register_route #### register_route
#### move_local_file_to_oss #### move_local_file_to_filesystem
#### oss_private_url #### filesystem_private_url
#### call_self_api #### call_self_api

View File

@@ -1,7 +1,6 @@
<?php <?php
namespace HyperfAdmin\Admin\Controller; namespace HyperfAdmin\Admin\Controller;
use OSS\Core\OssException;
use HyperfAdmin\BaseUtils\Constants\ErrorCode; use HyperfAdmin\BaseUtils\Constants\ErrorCode;
use HyperfAdmin\BaseUtils\Log; use HyperfAdmin\BaseUtils\Log;
use HyperfAdmin\BaseUtils\Scaffold\Controller\Controller; use HyperfAdmin\BaseUtils\Scaffold\Controller\Controller;
@@ -10,18 +9,21 @@ class UploadController extends Controller
{ {
public function image() public function image()
{ {
$bucket = $this->request->input('bucket', 'local');
$private = $this->request->input('private', false);
$file = $this->request->file('file'); $file = $this->request->file('file');
if(!$file->isValid()) { if (!$file->isValid()) {
return $this->fail(ErrorCode::CODE_ERR_PARAM); return $this->fail(ErrorCode::CODE_ERR_PARAM);
} }
$tmp_file = $file->toArray()['tmp_file']; $tmp_file = $file->toArray()['tmp_file'];
$md5_filename = md5_file($tmp_file); $md5_filename = md5_file($tmp_file);
$path = '1/' . date('Ym') . '/' . $md5_filename . '.' . $file->getExtension(); $path = '1/' . date('Ym') . '/' . $md5_filename . '.' . $file->getExtension();
$bucket = $this->request->input('bucket', 'aliyuncs');
$private = $this->request->input('private', false);
try { try {
$uploaded = move_local_file_to_oss($tmp_file, $path, $private, $bucket); $uploaded = move_local_file_to_filesystem($tmp_file, $path, $private, $bucket);
if($uploaded === false) { if ($uploaded === false) {
return $this->fail(ErrorCode::CODE_ERR_SERVER, '上传失败'); return $this->fail(ErrorCode::CODE_ERR_SERVER, '上传失败');
} }
[$width, $height] = getimagesize($tmp_file); [$width, $height] = getimagesize($tmp_file);
@@ -35,7 +37,7 @@ class UploadController extends Controller
]; ];
return $this->success($info); return $this->success($info);
} catch (OssException $e) { } catch (\Exception $e) {
Log::get('upload')->error($e->getMessage()); Log::get('upload')->error($e->getMessage());
return $this->fail(ErrorCode::CODE_ERR_SERVER, $e->getMessage()); return $this->fail(ErrorCode::CODE_ERR_SERVER, $e->getMessage());
@@ -45,11 +47,13 @@ class UploadController extends Controller
public function privateFileUrl() public function privateFileUrl()
{ {
$oss_path = $this->request->input('key'); $oss_path = $this->request->input('key');
if(!$oss_path) { $bucket = $this->request->input('storage', config('file.default'));
if (!$oss_path) {
return $this->fail(ErrorCode::CODE_ERR_PARAM); return $this->fail(ErrorCode::CODE_ERR_PARAM);
} }
$private_url = oss_private_url($oss_path); $private_url = filesystem_private_url($oss_path, MINUTE * 5, $bucket);
if(!$private_url) { if (!$private_url) {
return $this->fail(ErrorCode::CODE_ERR_SYSTEM); return $this->fail(ErrorCode::CODE_ERR_SYSTEM);
} }

View File

@@ -129,8 +129,8 @@ class ExportService
])->save(); ])->save();
$query['_page'] += 1; $query['_page'] += 1;
} }
$bucket = config('storager.export_service', config('storager.default')); $bucket = config('file.export_storage', config('file.default'));
$info = move_local_file_to_oss($file_path, '1/export_task/' . $file_name, true, $bucket); $info = move_local_file_to_filesystem($file_path, '1/export_task/' . $file_name, true, $bucket);
if($info) { if($info) {
$task->fill([ $task->fill([
'status' => ExportTasks::STATUS_SUCCESS, 'status' => ExportTasks::STATUS_SUCCESS,

View File

@@ -60,6 +60,9 @@
"src/Helper/common.php", "src/Helper/common.php",
"src/Helper/array.php", "src/Helper/array.php",
"src/Helper/system.php" "src/Helper/system.php"
],
"classmap": [
"src/classmap"
] ]
}, },
"autoload-dev": { "autoload-dev": {

View File

@@ -1,23 +1,23 @@
<?php <?php
use Hyperf\ExceptionHandler\Formatter\FormatterInterface; use Hyperf\ExceptionHandler\Formatter\FormatterInterface;
use Hyperf\Filesystem\FilesystemFactory;
use Hyperf\HttpServer\Router\DispatcherFactory; use Hyperf\HttpServer\Router\DispatcherFactory;
use Hyperf\HttpServer\Router\Router; use Hyperf\HttpServer\Router\Router;
use Hyperf\Server\ServerFactory; use Hyperf\Server\ServerFactory;
use Hyperf\Utils\Str; use Hyperf\Utils\Str;
use OSS\Core\OssException;
use HyperfAdmin\BaseUtils\AliyunOSS;
use HyperfAdmin\BaseUtils\Guzzle; use HyperfAdmin\BaseUtils\Guzzle;
use HyperfAdmin\BaseUtils\Log; use HyperfAdmin\BaseUtils\Log;
use League\Flysystem\AdapterInterface;
if(!function_exists('server')) { if (!function_exists('server')) {
function server() function server()
{ {
return container(ServerFactory::class); return container(ServerFactory::class);
} }
} }
if(!function_exists('swoole_server')) { if (!function_exists('swoole_server')) {
/** /**
* @return \Swoole\Server * @return \Swoole\Server
*/ */
@@ -27,7 +27,7 @@ if(!function_exists('swoole_server')) {
} }
} }
if(!function_exists('dispatcher')) { if (!function_exists('dispatcher')) {
/** /**
* @param $server_name * @param $server_name
* *
@@ -39,7 +39,7 @@ if(!function_exists('dispatcher')) {
} }
} }
if(!function_exists('register_route')) { if (!function_exists('register_route')) {
function register_route($prefix, $controller, $callable = null) function register_route($prefix, $controller, $callable = null)
{ {
Router::addGroup($prefix, function () use ($controller, $callable) { Router::addGroup($prefix, function () use ($controller, $callable) {
@@ -68,48 +68,88 @@ if(!function_exists('register_route')) {
} }
} }
if(!function_exists('move_local_file_to_oss')) { if (!function_exists('move_local_file_to_filesystem')) {
function move_local_file_to_oss($local_file_path, $oss_file_path, $private = false, $bucket = 'aliyuncs') function move_local_file_to_filesystem($local_file_path, $save_file_path, $private = false, $bucket = 'aliyuncs', $update_when_exist = true)
{ {
/** @var AliyunOSS $oss */ $filesystem = make(FilesystemFactory::class)->get($bucket);
$oss = make(AliyunOSS::class, ['bucket' => $bucket]);
try { try {
$method = $private ? 'uploadPrivateFile' : 'uploadFile'; $stream = fopen($local_file_path, 'r');
$oss->$method($oss_file_path, $local_file_path); $has = $filesystem->has($save_file_path);
$file_path = config('storager.aliyuncs.cdn') . '/' . $oss_file_path; if (!$has) {
if($private) { $filesystem->writeStream($save_file_path, $stream);
$file_path = oss_private_url($oss_file_path, MINUTE * 5, $bucket); }
if ($has && $update_when_exist) {
$filesystem->updateStream($save_file_path, $stream);
} }
if ($private) {
$filesystem->setVisibility($save_file_path, AdapterInterface::VISIBILITY_PRIVATE);
}
$meta = $filesystem->getMetadata($save_file_path);
switch (config("file.storage.{$bucket}.driver")) {
case \Hyperf\Filesystem\Adapter\LocalAdapterFactory::class:
$file_path = config("file.storage.{$bucket}.cdn") . $meta['path'];
break;
case \Hyperf\Filesystem\Adapter\AliyunOssAdapterFactory::class;
$file_path = $meta['info']['url'];
break;
// TODO 更多 filesystem 渠道
default:
$file_path = $save_file_path;
}
if ($private) {
$file_path = filesystem_private_url($save_file_path, MINUTE * 5, $bucket);
}
return [ return [
'file_path' => $file_path, 'file_path' => $file_path, // 直接可访问的完整链接
'path' => 'oss/' . $oss_file_path, 'path' => $save_file_path, // 资源的存储路径
]; ];
} catch (OssException $exception) { } catch (\Exception $exception) {
Log::get('move_local_file_to_oss')->error($exception->getMessage()); Log::get('move_local_file_to_filesystem')->error($exception->getMessage());
return false; return false;
} }
} }
} }
if(!function_exists('oss_private_url')) { if (!function_exists('filesystem_private_url')) {
function oss_private_url($oss_file_path, $timeout = 60, $bucket = 'aliyuncs') function filesystem_private_url($save_file_path, $timeout = 60, $bucket = 'aliyuncs')
{ {
/** @var AliyunOSS $oss */ if (!$save_file_path) {
$oss = make(AliyunOSS::class, ['bucket' => $bucket]); return false;
$key = preg_replace('@^oss/@', '', $oss_file_path); }
$filesystem = make(FilesystemFactory::class)->get($bucket);
if (Str::startsWith($save_file_path, 'http')) {
$save_file_path = parse_url($save_file_path)['path'];
$parts = explode('/', $save_file_path);
unset($parts[0]);
$save_file_path = implode('/', $parts);
}
$save_file_path = preg_replace('@^oss/@', '', $save_file_path);
try { try {
return str_replace('-internal', '', $oss->getSignUrl($key, $timeout)); switch (config("file.storage.{$bucket}.driver")) {
} catch (OssException $exception) { case \Hyperf\Filesystem\Adapter\LocalAdapterFactory::class:
Log::get('oss_private_url')->error($exception->getMessage()); return config("file.storage.{$bucket}.cdn") . $save_file_path;
break;
case \Hyperf\Filesystem\Adapter\AliyunOssAdapterFactory::class;
$adapter = $filesystem->getAdapter();
if (method_exists($adapter, 'signUrl')) {
return $adapter->signUrl($save_file_path, $timeout);
}
break;
// TODO 更多 filesystem 渠道
default:
return $save_file_path;
}
} catch (\Exception $exception) {
Log::get('filesystem_private_url')->error($exception->getMessage());
return false; return false;
} }
} }
} }
if(!function_exists('call_self_api')) { if (!function_exists('call_self_api')) {
function call_self_api($api, $params = [], $method = 'GET') function call_self_api($api, $params = [], $method = 'GET')
{ {
$headers = [ $headers = [
@@ -121,12 +161,12 @@ if(!function_exists('call_self_api')) {
} }
} }
if(!function_exists('select_options')) { if (!function_exists('select_options')) {
function select_options($api, array $kws) function select_options($api, array $kws)
{ {
$ret = []; $ret = [];
$chunk = array_chunk($kws, 100); $chunk = array_chunk($kws, 100);
foreach($chunk as $part) { foreach ($chunk as $part) {
$ret = array_merge($ret, call_self_api($api, ['kw' => implode(',', $part)])); $ret = array_merge($ret, call_self_api($api, ['kw' => implode(',', $part)]));
} }
@@ -134,17 +174,17 @@ if(!function_exists('select_options')) {
} }
} }
if(!function_exists('process_list_filter')) { if (!function_exists('process_list_filter')) {
function process_list_filter($processes, $rule) function process_list_filter($processes, $rule)
{ {
if(!$rule) { if (!$rule) {
return $processes; return $processes;
} }
if($ignore = $rule['ignore'] ?? false) { if ($ignore = $rule['ignore'] ?? false) {
if(is_string($ignore) && $ignore === 'all') { if (is_string($ignore) && $ignore === 'all') {
$processes = []; $processes = [];
} }
if(is_array($ignore)) { if (is_array($ignore)) {
$processes = array_filter($processes, function ($item) use ($ignore) { $processes = array_filter($processes, function ($item) use ($ignore) {
return !Str::startsWith($item, array_map(function ($each) { return !Str::startsWith($item, array_map(function ($each) {
return Str::replaceLast('*', '', $each); return Str::replaceLast('*', '', $each);
@@ -152,7 +192,7 @@ if(!function_exists('process_list_filter')) {
}); });
} }
} }
if($active = $rule['active'] ?? []) { if ($active = $rule['active'] ?? []) {
$processes = array_merge($processes, $active); $processes = array_merge($processes, $active);
} }
@@ -160,17 +200,13 @@ if(!function_exists('process_list_filter')) {
} }
} }
if(!function_exists('get_sub_dir')) { if (!function_exists('get_sub_dir')) {
function get_sub_dir($dir, $exclude = []) function get_sub_dir($dir, $exclude = [])
{ {
$paths = []; $paths = [];
$dirs = \Symfony\Component\Finder\Finder::create() $dirs = \Symfony\Component\Finder\Finder::create()->in($dir)->depth('<1')->exclude((array)$exclude)->directories();
->in($dir)
->depth('<1')
->exclude((array)$exclude)
->directories();
/** @var SplFileInfo $dir */ /** @var SplFileInfo $dir */
foreach($dirs as $dir) { foreach ($dirs as $dir) {
$paths[] = $dir->getRealPath(); $paths[] = $dir->getRealPath();
} }
@@ -178,7 +214,7 @@ if(!function_exists('get_sub_dir')) {
} }
} }
if(!function_exists('db_complete')) { if (!function_exists('db_complete')) {
function db_complete(array $conf) function db_complete(array $conf)
{ {
return array_overlay($conf, [ return array_overlay($conf, [

View File

@@ -49,10 +49,14 @@ class HttpLogMiddleware implements MiddlewareInterface
case Dispatcher::FOUND: case Dispatcher::FOUND:
if(!in_array($path, $uriEx)) { if(!in_array($path, $uriEx)) {
$response_content = mb_substr($response->getBody()->getContents(), 0, 125); $response_content = mb_substr($response->getBody()->getContents(), 0, 125);
$request_content = $request->getBody()->getContents();
if (preg_match('/filename=.(.*)/', $request_content, $m)) {
$request_content = urlencode($m[1]);
}
$msg = [ $msg = [
'referer' => $referer, 'referer' => $referer,
'uri' => $request->getRequestTarget(), 'uri' => $request->getRequestTarget(),
'request' => $request->getBody()->getContents(), 'request' => $request_content,
'use_time' => 1000 * (microtime(true) - $start_time), 'use_time' => 1000 * (microtime(true) - $start_time),
'response' => $response_content, 'response' => $response_content,
]; ];

View File

@@ -265,7 +265,7 @@ abstract class AbstractController extends Controller
if (is_callable($item['render'])) { if (is_callable($item['render'])) {
$each[$item['field']] = $item['render']($each[$item['field']] ?? null, $each); $each[$item['field']] = $item['render']($each[$item['field']] ?? null, $each);
} elseif (is_string($item['render']) && method_exists($this, $item['render'])) { } elseif (is_string($item['render']) && method_exists($this, $item['render'])) {
$each[$item['field']] = $this->$item['render']($each[$item['field']] ?? null, $each); $each[$item['field']] = $this->{$item['render']}($each[$item['field']] ?? null, $each);
} }
unset($each); unset($each);
} }

View File

@@ -0,0 +1,451 @@
<?php
/**
* 增加此文件的目的是因为原生的类中缺少更多 AliyunOSS 底层的更多方法
* 增加的方法有
* signUrl 获取文件的私有访问地址
*/
namespace Xxtime\Flysystem\Aliyun;
use League\Flysystem\Adapter\AbstractAdapter;
use League\Flysystem\Config;
use League\Flysystem\Util;
use OSS\OssClient;
use Exception;
class OssAdapter extends AbstractAdapter
{
/**
* @var Supports
*/
public $supports;
/**
* @var OssClient
*/
private $oss;
/**
* @var AliYun bucket
*/
private $bucket;
/**
* @var string
*/
private $endpoint = 'oss-cn-hangzhou.aliyuncs.com';
/**
* OssAdapter constructor.
* @param array $config
* @throws Exception
*/
public function __construct($config = [])
{
$isCName = false;
$token = null;
$this->supports = new Supports();
try {
$this->bucket = $config['bucket'];
empty($config['endpoint']) ? null : $this->endpoint = $config['endpoint'];
empty($config['timeout']) ? $config['timeout'] = 3600 : null;
empty($config['connectTimeout']) ? $config['connectTimeout'] = 10 : null;
if (!empty($config['isCName'])) {
$isCName = true;
}
if (!empty($config['token'])) {
$token = $config['token'];
}
$this->oss = new OssClient(
$config['accessId'], $config['accessSecret'], $this->endpoint, $isCName, $token
);
$this->oss->setTimeout($config['timeout']);
$this->oss->setConnectTimeout($config['connectTimeout']);
} catch (Exception $e) {
throw $e;
}
}
/**
* Write a new file.
*
* @param string $path
* @param string $contents
* @param Config $config Config object
*
* @return array|false false on failure file meta data on success
*/
public function write($path, $contents, Config $config)
{
$result = $this->oss->putObject($this->bucket, $path, $contents, $this->getOssOptions($config));
$this->supports->setFlashData($result);
return $result;
}
/**
* Write a new file using a stream.
*
* @param string $path
* @param resource $resource
* @param Config $config Config object
*
* @return array|false false on failure file meta data on success
*/
public function writeStream($path, $resource, Config $config)
{
if (!is_resource($resource)) {
return false;
}
$i = 0;
$bufferSize = 1000000; // 1M
while (!feof($resource)) {
if (false === $buffer = fread($resource, $block = $bufferSize)) {
return false;
}
$position = $i * $bufferSize;
$size = $this->oss->appendObject($this->bucket, $path, $buffer, $position, $this->getOssOptions($config));
$i++;
}
fclose($resource);
return true;
}
/**
* Update a file.
*
* @param string $path
* @param string $contents
* @param Config $config Config object
*
* @return array|false false on failure file meta data on success
*/
public function update($path, $contents, Config $config)
{
$result = $this->oss->putObject($this->bucket, $path, $contents, $this->getOssOptions($config));
$this->supports->setFlashData($result);
return $result;
}
/**
* Update a file using a stream.
*
* @param string $path
* @param resource $resource
* @param Config $config Config object
*
* @return array|false false on failure file meta data on success
*/
public function updateStream($path, $resource, Config $config)
{
$result = $this->write($path, stream_get_contents($resource), $config);
if (is_resource($resource)) {
fclose($resource);
}
return $result;
}
/**
* Rename a file.
*
* @param string $path
* @param string $newpath
*
* @return bool
*/
public function rename($path, $newpath)
{
$this->oss->copyObject($this->bucket, $path, $this->bucket, $newpath);
$this->oss->deleteObject($this->bucket, $path);
return true;
}
/**
* Copy a file.
*
* @param string $path
* @param string $newpath
*
* @return bool
*/
public function copy($path, $newpath)
{
$this->oss->copyObject($this->bucket, $path, $this->bucket, $newpath);
return true;
}
/**
* Delete a file.
*
* @param string $path
*
* @return bool
*/
public function delete($path)
{
$this->oss->deleteObject($this->bucket, $path);
return true;
}
/**
* Delete a directory.
*
* @param string $dirname
*
* @return bool
*/
public function deleteDir($dirname)
{
$lists = $this->listContents($dirname, true);
if (!$lists) {
return false;
}
$objectList = [];
foreach ($lists as $value) {
$objectList[] = $value['path'];
}
$this->oss->deleteObjects($this->bucket, $objectList);
return true;
}
/**
* Create a directory.
*
* @param string $dirname directory name
* @param Config $config
*
* @return array|false
*/
public function createDir($dirname, Config $config)
{
$this->oss->createObjectDir($this->bucket, $dirname);
return true;
}
/**
* Set the visibility for a file.
*
* @param string $path
* @param string $visibility
*
* @return array|false file meta data
*
* Aliyun OSS ACL value: 'default', 'private', 'public-read', 'public-read-write'
*/
public function setVisibility($path, $visibility)
{
$this->oss->putObjectAcl(
$this->bucket,
$path,
($visibility == 'public') ? 'public-read' : 'private'
);
return true;
}
/**
* Check whether a file exists.
*
* @param string $path
*
* @return array|bool|null
*/
public function has($path)
{
return $this->oss->doesObjectExist($this->bucket, $path);
}
/**
* Read a file.
*
* @param string $path
*
* @return array|false
*/
public function read($path)
{
return [
'contents' => $this->oss->getObject($this->bucket, $path)
];
}
/**
* Read a file as a stream.
*
* @param string $path
*
* @return array|false
*/
public function readStream($path)
{
$resource = 'http://' . $this->bucket . '.' . $this->endpoint . '/' . $path;
return [
'stream' => $resource = fopen($resource, 'r')
];
}
/**
* List contents of a directory.
*
* @param string $directory
* @param bool $recursive
*
* @return array
*/
public function listContents($directory = '', $recursive = false)
{
$directory = rtrim($directory, '\\/');
$result = [];
$nextMarker = '';
while (true) {
// max-keys 用于限定此次返回object的最大数如果不设定默认为100max-keys取值不能大于1000。
// prefix 限定返回的object key必须以prefix作为前缀。注意使用prefix查询时返回的key中仍会包含prefix。
// delimiter是一个用于对Object名字进行分组的字符。所有名字包含指定的前缀且第一次出现delimiter字符之间的object作为一组元素
// marker 用户设定结果从marker之后按字母排序的第一个开始返回。
$options = [
'max-keys' => 1000,
'prefix' => $directory . '/',
'delimiter' => '/',
'marker' => $nextMarker,
];
$res = $this->oss->listObjects($this->bucket, $options);
// 得到nextMarker从上一次$res读到的最后一个文件的下一个文件开始继续获取文件列表
$nextMarker = $res->getNextMarker();
$prefixList = $res->getPrefixList(); // 目录列表
$objectList = $res->getObjectList(); // 文件列表
if ($prefixList) {
foreach ($prefixList as $value) {
$result[] = [
'type' => 'dir',
'path' => $value->getPrefix()
];
if ($recursive) {
$result = array_merge($result, $this->listContents($value->getPrefix(), $recursive));
}
}
}
if ($objectList) {
foreach ($objectList as $value) {
if (($value->getSize() === 0) && ($value->getKey() === $directory . '/')) {
continue;
}
$result[] = [
'type' => 'file',
'path' => $value->getKey(),
'timestamp' => strtotime($value->getLastModified()),
'size' => $value->getSize()
];
}
}
if ($nextMarker === '') {
break;
}
}
return $result;
}
/**
* Get all the meta data of a file or directory.
*
* @param string $path
*
* @return array|false
*/
public function getMetadata($path)
{
return $this->oss->getObjectMeta($this->bucket, $path);
}
/**
* Get the size of a file.
*
* @param string $path
*
* @return array|false
*/
public function getSize($path)
{
$response = $this->oss->getObjectMeta($this->bucket, $path);
return [
'size' => $response['content-length']
];
}
/**
* Get the mimetype of a file.
*
* @param string $path
*
* @return array|false
*/
public function getMimetype($path)
{
$response = $this->oss->getObjectMeta($this->bucket, $path);
return [
'mimetype' => $response['content-type']
];
}
/**
* Get the timestamp of a file.
*
* @param string $path
*
* @return array|false
*/
public function getTimestamp($path)
{
$response = $this->oss->getObjectMeta($this->bucket, $path);
return [
'timestamp' => $response['last-modified']
];
}
/**
* Get the visibility of a file.
*
* @param string $path
*
* @return array|false
*/
public function getVisibility($path)
{
$response = $this->oss->getObjectAcl($this->bucket, $path);
return [
'visibility' => $response,
];
}
/**
* Get OSS Options
* @param Config $config
* @return array
*/
private function getOssOptions(Config $config)
{
$options = [];
if ($config->has("headers")) {
$options['headers'] = $config->get("headers");
}
if ($config->has("Content-Type")) {
$options["Content-Type"] = $config->get("Content-Type");
}
if ($config->has("Content-Md5")) {
$options["Content-Md5"] = $config->get("Content-Md5");
$options["checkmd5"] = false;
}
return $options;
}
public function signUrl($path, $timeout = 60)
{
return $this->oss->signUrl($this->bucket, $path, $timeout);
}
}

View File

@@ -18,26 +18,24 @@ abstract class ClassJobAbstract
$this->job = $crontab; $this->job = $crontab;
$this->jobManager = make(CronManager::class); $this->jobManager = make(CronManager::class);
$this->state = $this->jobManager->getJobState($crontab->getId()); $this->state = $this->jobManager->getJobState($crontab->getId());
$this->logger = logger(); $this->logger = logger()->get('cron_center');
} }
public function run($params = []) public function run($params = [])
{ {
$func = function () use ($params) { try {
try { $this->beforeAction($params);
$this->beforeAction($params); $result = $this->handle($params);
$this->handle($params); $this->afterAction($params);
$this->afterAction($params); return $result;
} catch (\Throwable $throwable) { } catch (\Throwable $throwable) {
$this->onError($throwable); $this->onError($throwable);
} finally { return false;
$this->onComplete(); } finally {
$this->onComplete();
return $this->evaluate(); return $this->evaluate();
} }
};
return $func();
} }
public function beforeAction($params = []) public function beforeAction($params = [])