文件系统

文件系统组件集成了 PHP 生态中大名鼎鼎的 League\Flysystem (这也是 Laravel 等诸多知名框架的底层库)。通过合理抽象,程序不必感知存储引擎究竟是本地硬盘还是云服务器,实现解耦。本组件对常用的云存储服务提供了协程化支持。

安装

  1. composer require hyperf/filesystem

League\Flysystem 组件 v1.0v2.0 版本变动较大,所以需要根据不同的版本,安装对应的适配器

  • 阿里云 OSS 适配器

Flysystem v1.0 版本

  1. composer require xxtime/flysystem-aliyun-oss

Flysystem v2.0 版本

  1. composer require hyperf/flysystem-oss
  • S3 适配器

Flysystem v1.0 版本

  1. composer require "league/flysystem-aws-s3-v3:^1.0"
  2. composer require hyperf/guzzle

Flysystem v2.0 版本

  1. composer require "league/flysystem-aws-s3-v3:^2.0"
  2. composer require hyperf/guzzle
  • 七牛适配器

Flysystem v1.0 版本

  1. composer require "overtrue/flysystem-qiniu:^1.0"

Flysystem v2.0 版本

  1. composer require "overtrue/flysystem-qiniu:^2.0"
  • 内存适配器

Flysystem v1.0 版本

  1. composer require "league/flysystem-memory:^1.0"

Flysystem v2.0 版本

  1. composer require "league/flysystem-memory:^2.0"
  • 腾讯云 COS 适配器

Flysystem v1.0 版本

flysystem-cos v2.0 版本已经不推荐使用了,请按照最新的文档修改为 3.0 版本

  1. composer require "overtrue/flysystem-cos:^3.0"

Flysystem v2.0 版本

  1. composer require "overtrue/flysystem-cos:^4.0"

安装完成后,执行

  1. php bin/hyperf.php vendor:publish hyperf/filesystem

就会生成 config/autoload/file.php 文件。在该文件中设置默认驱动,并配置对应驱动的 access key、access secret 等信息就可以使用了。

使用

通过 DI 注入 League\Flysystem\Filesystem 即可使用。

API 如下:

以下示例为 Flysystem v1.0 版本,v2.0 版本请看官方文档

  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Controller;
  4. class IndexController extends AbstractController
  5. {
  6. public function example(\League\Flysystem\Filesystem $filesystem)
  7. {
  8. // Process Upload
  9. $file = $this->request->file('upload');
  10. $stream = fopen($file->getRealPath(), 'r+');
  11. $filesystem->writeStream(
  12. 'uploads/'.$file->getClientFilename(),
  13. $stream
  14. );
  15. fclose($stream);
  16. // Write Files
  17. $filesystem->write('path/to/file.txt', 'contents');
  18. // Add local file
  19. $stream = fopen('local/path/to/file.txt', 'r+');
  20. $result = $filesystem->writeStream('path/to/file.txt', $stream);
  21. if (is_resource($stream)) {
  22. fclose($stream);
  23. }
  24. // Update Files
  25. $filesystem->update('path/to/file.txt', 'new contents');
  26. // Check if a file exists
  27. $exists = $filesystem->has('path/to/file.txt');
  28. // Read Files
  29. $contents = $filesystem->read('path/to/file.txt');
  30. // Delete Files
  31. $filesystem->delete('path/to/file.txt');
  32. // Rename Files
  33. $filesystem->rename('filename.txt', 'newname.txt');
  34. // Copy Files
  35. $filesystem->copy('filename.txt', 'duplicate.txt');
  36. // list the contents
  37. $filesystem->listContents('path', false);
  38. }
  39. }

在某些时候,您会需要同时使用多种存储媒介。这时可以注入 Hyperf\Filesystem\FilesystemFactory 来动态选择使用哪种驱动。

  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Controller;
  4. class IndexController
  5. {
  6. public function example(\Hyperf\Filesystem\FilesystemFactory $factory)
  7. {
  8. $local = $factory->get('local');
  9. // Write Files
  10. $local->write('path/to/file.txt', 'contents');
  11. $s3 = $factory->get('s3');
  12. $s3->write('path/to/file.txt', 'contents');
  13. }
  14. }

配置静态资源

如果您希望通过 http 访问上传到本地的文件,请在 config/autoload/server.php 配置中增加以下配置。

  1. return [
  2. 'settings' => [
  3. ...
  4. // 将 public 替换为上传目录
  5. 'document_root' => BASE_PATH . '/public',
  6. 'enable_static_handler' => true,
  7. ],
  8. ];

注意事项

  1. S3 存储请确认安装 hyperf/guzzle 组件以提供协程化支持。阿里云、七牛云、腾讯云云存储请开启 Curl Hook来使用协程。因 Curl Hook 的参数支持性问题,请使用 Swoole 4.4.13 以上版本。
  2. minIO, ceph radosgw 等私有对象存储方案均支持 S3 协议,可以使用 S3 适配器。
  3. 使用 Local 驱动时,根目录是配置好的地址,而不是操作系统的根目录。例如,Local 驱动 root 设置为 /var/www, 则本地磁盘上的 /var/www/public/file.txt 通过 flysystem API 访问时应使用 /public/file.txtpublic/file.txt
  4. 以阿里云 OSS 为例,1 核 1 进程读操作性能对比:
  1. ab -k -c 10 -n 1000 http://127.0.0.1:9501/

未开启 CURL HOOK:

  1. Concurrency Level: 10
  2. Time taken for tests: 202.902 seconds
  3. Complete requests: 1000
  4. Failed requests: 0
  5. Keep-Alive requests: 1000
  6. Total transferred: 146000 bytes
  7. HTML transferred: 5000 bytes
  8. Requests per second: 4.93 [#/sec] (mean)
  9. Time per request: 2029.016 [ms] (mean)
  10. Time per request: 202.902 [ms] (mean, across all concurrent requests)
  11. Transfer rate: 0.70 [Kbytes/sec] received

开启 CURL HOOK 后:

  1. Concurrency Level: 10
  2. Time taken for tests: 9.252 seconds
  3. Complete requests: 1000
  4. Failed requests: 0
  5. Keep-Alive requests: 1000
  6. Total transferred: 146000 bytes
  7. HTML transferred: 5000 bytes
  8. Requests per second: 108.09 [#/sec] (mean)
  9. Time per request: 92.515 [ms] (mean)
  10. Time per request: 9.252 [ms] (mean, across all concurrent requests)
  11. Transfer rate: 15.41 [Kbytes/sec] received

详细配置

  1. return [
  2. // 选择storage下对应驱动的键即可。
  3. 'default' => 'local',
  4. 'storage' => [
  5. 'local' => [
  6. 'driver' => \Hyperf\Filesystem\Adapter\LocalAdapterFactory::class,
  7. 'root' => __DIR__ . '/../../runtime',
  8. ],
  9. 'ftp' => [
  10. 'driver' => \Hyperf\Filesystem\Adapter\FtpAdapterFactory::class,
  11. 'host' => 'ftp.example.com',
  12. 'username' => 'username',
  13. 'password' => 'password',
  14. /* optional config settings */
  15. 'port' => 21,
  16. 'root' => '/path/to/root',
  17. 'passive' => true,
  18. 'ssl' => true,
  19. 'timeout' => 30,
  20. 'ignorePassiveAddress' => false,
  21. ],
  22. 'memory' => [
  23. 'driver' => \Hyperf\Filesystem\Adapter\MemoryAdapterFactory::class,
  24. ],
  25. 's3' => [
  26. 'driver' => \Hyperf\Filesystem\Adapter\S3AdapterFactory::class,
  27. 'credentials' => [
  28. 'key' => env('S3_KEY'),
  29. 'secret' => env('S3_SECRET'),
  30. ],
  31. 'region' => env('S3_REGION'),
  32. 'version' => 'latest',
  33. 'bucket_endpoint' => false,
  34. 'use_path_style_endpoint' => false,
  35. 'endpoint' => env('S3_ENDPOINT'),
  36. 'bucket_name' => env('S3_BUCKET'),
  37. ],
  38. 'minio' => [
  39. 'driver' => \Hyperf\Filesystem\Adapter\S3AdapterFactory::class,
  40. 'credentials' => [
  41. 'key' => env('S3_KEY'),
  42. 'secret' => env('S3_SECRET'),
  43. ],
  44. 'region' => env('S3_REGION'),
  45. 'version' => 'latest',
  46. 'bucket_endpoint' => false,
  47. 'use_path_style_endpoint' => true,
  48. 'endpoint' => env('S3_ENDPOINT'),
  49. 'bucket_name' => env('S3_BUCKET'),
  50. ],
  51. 'oss' => [
  52. 'driver' => \Hyperf\Filesystem\Adapter\AliyunOssAdapterFactory::class,
  53. 'accessId' => env('OSS_ACCESS_ID'),
  54. 'accessSecret' => env('OSS_ACCESS_SECRET'),
  55. 'bucket' => env('OSS_BUCKET'),
  56. 'endpoint' => env('OSS_ENDPOINT'),
  57. // 'timeout' => 3600,
  58. // 'connectTimeout' => 10,
  59. // 'isCName' => false,
  60. // 'token' => '',
  61. ],
  62. 'qiniu' => [
  63. 'driver' => \Hyperf\Filesystem\Adapter\QiniuAdapterFactory::class,
  64. 'accessKey' => env('QINIU_ACCESS_KEY'),
  65. 'secretKey' => env('QINIU_SECRET_KEY'),
  66. 'bucket' => env('QINIU_BUCKET'),
  67. 'domain' => env('QINIU_DOMAIN'),
  68. ],
  69. 'cos' => [
  70. 'driver' => \Hyperf\Filesystem\Adapter\CosAdapterFactory::class,
  71. 'region' => env('COS_REGION'),
  72. // overtrue/flysystem-cos ^2.0 配置如下
  73. 'credentials' => [
  74. 'appId' => env('COS_APPID'),
  75. 'secretId' => env('COS_SECRET_ID'),
  76. 'secretKey' => env('COS_SECRET_KEY'),
  77. ],
  78. // overtrue/flysystem-cos ^3.0 配置如下
  79. 'app_id' => env('COS_APPID'),
  80. 'secret_id' => env('COS_SECRET_ID'),
  81. 'secret_key' => env('COS_SECRET_KEY'),
  82. // 可选,如果 bucket 为私有访问请打开此项
  83. // 'signed_url' => false,
  84. 'bucket' => env('COS_BUCKET'),
  85. 'read_from_cdn' => false,
  86. // 'timeout' => 60,
  87. // 'connect_timeout' => 60,
  88. // 'cdn' => '',
  89. // 'scheme' => 'https',
  90. ],
  91. ],
  92. ];