官网地址:Hyperf
一 安装
#安装源码
composer require hyperf/filesystem
#安装配置文件
php bin/hyperf.php vendor:publish hyperf/filesystem
#七牛云sdk
composer require overtrue/flysystem-qiniu
#config/autoload/file.php
return [
'default' => 'local',//默认local驱动
'storage' => [
'local' => [
'driver' => \Hyperf\Filesystem\Adapter\LocalAdapterFactory::class,
'root' => __DIR__ . '/../../runtime',//默认上传位置
],
'qiniu' => [
'driver' => \Hyperf\Filesystem\Adapter\QiniuAdapterFactory::class,
'accessKey' => env('QINIU_ACCESS_KEY'),
'secretKey' => env('QINIU_SECRET_KEY'),
'bucket' => env('QINIU_BUCKET'),
'domain' => env('QINIU_DOMAIN'),
],
……
]
];
二 使用
本地上传,获取上传文件,并获取文件流。将上传目录和文件流作为参数,调用上传函数。
#App\Controller\TestController
#文件上传
public function uploadfile(Filesystem $filesystem)
{
//本地上传
$file = $this->request->file('upload');
$stream = fopen($file->getRealPath(), 'r+');
$filesystem->writeStream(
'uploads/' . $file->getClientFilename(),
$stream
);
fclose($stream);
}
public function uploadfile3(FilesystemFactory $factory)
{
//本地上传
$local = $factory->get('local');
var_dump(get_class($local));
$file = $this->request->file('upload');
$filepath = 'uploads/' . $file->getClientFilename();
$stream = fopen($file->getRealPath(), 'r+');
// Write Files
$local->writeStream($filepath, $stream);
fclose($stream);
}
#七牛云上传
public function uploadfile2(FilesystemFactory $factory)
{
$qiniu = $factory->get('qiniu');
$file = $this->request->file('upload');
$filepath = 'uploads/' . $file->getClientFilename();
$stream = fopen($file->getRealPath(), 'r+');
// Write Files
$qiniu->writeStream($filepath, $stream);
}
三 解析
不用使用中间件和监听器,原理比较简单。
直接注入\League\Flysystem\Filesystem,和通过注入\Hyperf\Filesystem\FilesystemFactory后调用FilesystemFactory::get(’local‘),效果相同,都是获取\League\Flysystem\Filesystem实例。
FilesystemFactory::get()可以根据参数不同,获取不同驱动,但需要其他驱动对应的sdk。
若没有设置配置文件,代码默认设置为local内容。所以没设置配置文件,本地上传也能用。
默认本地上传位置是runtime,不便于开发。因为runtime一般是运行时的缓存文件,和上传文件应该分开。
根据开发和维护经验,开发中上传的图片最好存在存储对象中,且对应的存储桶不挂载到磁盘上。因为有些服务器中某些安全性质的软件,比如腾讯云的云景,会全盘扫描文件。所以盘上文件越多,下行流量消耗会多……费钱……
代码如下
#Hyperf\Filesystem\FilesystemFactory
class FilesystemFactory
{
/**
* @var ContainerInterface
*/
private $container;
/**
* @var ConfigInterface
*/
private $config;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
$this->config = $container->get(ConfigInterface::class);
}
public function get($adapterName): Filesystem
{
$options = $this->config->get('file', [
'default' => 'local',
'storage' => [
'local' => [
'driver' => LocalAdapterFactory::class,
'root' => BASE_PATH . '/runtime',
],
],
]);
$adapter = $this->getAdapter($options, $adapterName);
if (Version::isV2()) {
return new Filesystem($adapter, $options['storage'][$adapterName] ?? []);
}
return new Filesystem($adapter, new Config($options['storage'][$adapterName]));
}
public function getAdapter($options, $adapterName)
{
if (! $options['storage'] || ! $options['storage'][$adapterName]) {
throw new InvalidArgumentException("file configurations are missing {$adapterName} options");
}
/** @var AdapterFactoryInterface $driver */
$driver = $this->container->get($options['storage'][$adapterName]['driver']);
return $driver->make($options['storage'][$adapterName]);
}
}
#Hyperf\Filesystem\Adapter\QiniuAdapterFactory
class QiniuAdapterFactory implements AdapterFactoryInterface
{
public function make(array $options)
{
return new QiniuAdapter($options['accessKey'], $options['secretKey'], $options['bucket'], $options['domain']);
}
}
#Overtrue\Flysystem\Qiniu\QiniuAdapter
public function write(string $path, string $contents, Config $config): void
{
……
}
public function writeStream(string $path, $contents, Config $config): void
{
……
}
public function move(string $source, string $destination, Config $config): void
{
……
}
public function copy(string $source, string $destination, Config $config): void
{
……
}
public function delete(string $path): void
{
……
}
类似于QiniuAdapter文件还用更多文件操作方法,详细可以看源码。