mycademy/yii2-file-storage

为Yii2提供的文件存储抽象层

安装: 2,411

依赖者: 0

建议者: 0

安全性: 0

星级: 2

关注者: 1

分支: 30

开放问题: 0

类型:yii2-extension

1.3.0 2021-12-05 22:41 UTC

This package is auto-updated.

Last update: 2024-09-06 04:54:35 UTC


README

此扩展为Yii2提供文件存储抽象层。

它是由https://github.com/yii2tech/file-storage@klimov-paul分叉的。由于原始存储库已被归档,此分叉旨在继续开发并保持与其依赖项(例如aws-sdk-php)的新版本兼容。

有关许可信息,请参阅LICENSE文件。

Latest Stable Version Total Downloads Build Status

安装

安装此扩展的首选方法是使用composer

运行以下命令之一:

php composer.phar require --prefer-dist mycademy/yii2-file-storage

或者添加以下内容到您的composer.json文件的require部分:

"mycademy/yii2-file-storage": "*"

如果您想使用Amazon S3存储,您还应该安装aws/aws-sdk-php版本2。运行以下命令:

php composer.phar require --prefer-dist aws/aws-sdk-php:~2.0

或者添加以下内容到您的composer.json文件的require部分:

"aws/aws-sdk-php": "~3.172"

如果您想使用MongoDB存储,您还应该安装yiisoft/yii2-mongodb版本2.1。运行以下命令:

php composer.phar require --prefer-dist yiisoft/yii2-mongodb:~2.1.0

或者添加以下内容到您的composer.json文件的require部分:

"yiisoft/yii2-mongodb": "2.1.0"

使用方法

此扩展为Yii2提供文件存储抽象层。此抽象引入了两个主要术语:“存储”和“存储桶”。“存储”是指能够使用某种特定方法存储文件的单元。“存储桶”是存储的逻辑部分,具有自己的特定属性并服务于某些逻辑目的。每次需要读取/写入文件时,都应该通过特定的存储桶进行,该存储桶始终属于文件存储。

示例应用程序配置

return [
    'components' => [
        'fileStorage' => [
            'class' => 'mycademy\yii2filestorage\local\Storage',
            'basePath' => '@webroot/files',
            'baseUrl' => '@web/files',
            'dirPermission' => 0775,
            'filePermission' => 0755,
            'buckets' => [
                'tempFiles' => [
                    'baseSubPath' => 'temp',
                    'fileSubDirTemplate' => '{^name}/{^^name}',
                ],
                'imageFiles' => [
                    'baseSubPath' => 'image',
                    'fileSubDirTemplate' => '{ext}/{^name}/{^^name}',
                ],
            ]
        ],
        // ...
    ],
    // ...
];

示例用法

$bucket = Yii::$app->fileStorage->getBucket('tempFiles');

$bucket->saveFileContent('foo.txt', 'Foo content'); // create file with content
$bucket->deleteFile('foo.txt'); // deletes file from bucket
$bucket->copyFileIn('/path/to/source/file.txt', 'file.txt'); // copy file into the bucket
$bucket->copyFileOut('file.txt', '/path/to/destination/file.txt'); // copy file from the bucket
var_dump($bucket->fileExists('file.txt')); // outputs `true`
echo $bucket->getFileUrl('file.txt'); // outputs: 'http://domain.com/files/f/i/file.txt'

此扩展提供了以下文件存储:

  • [[\mycademy\yii2filestorage\local\Storage]] - 在OS本地文件系统中存储文件。
  • [[\mycademy\yii2filestorage\sftp\Storage]] - 使用SSH2 SFTP存储文件。
  • [[\mycademy\yii2filestorage\amazon\Storage]] - 使用Amazon简单存储服务(S3)存储文件。
  • [[\mycademy\yii2filestorage\mongodb\Storage]] - 使用MongoDB GridFS存储文件。
  • [[\mycademy\yii2filestorage\hub\Storage]] - 允许组合不同的文件存储。

请参阅特定存储类的文档以获取更多详细信息。

请注意!某些存储可能需要安装默认不包含此包的附加库或PHP扩展。请检查特定存储类的文档以获取详细信息。

抽象使用

每个提供的存储都实现了用于文件处理的相同接口。因此,每个存储都可以替代另一个,除非程序代码遵循此接口。这允许您在无需调整程序源代码的情况下在存储之间切换。例如,在生产服务器上,您可能需要使用SFTP进行文件存储,并且应用程序配置如下所示:

return [
    'components' => [
        'fileStorage' => [
            'class' => 'mycademy\yii2filestorage\sftp\Storage',
            'ssh' => [
                'host' => 'file.server.com',
                'username' => 'user',
                'password' => 'some-password',
            ],
            'basePath' => '/var/www/html/files',
            'baseUrl' => 'http://file.server.com/files',
            'buckets' => [
                'temp',
                'item',
            ]
        ],
        // ...
    ],
    // ...
];

然而,在开发环境中,您可以使用简单的本地文件存储

return [
    'components' => [
        'fileStorage' => [
            'class' => 'mycademy\yii2filestorage\local\Storage',
            'basePath' => '@webroot/files',
            'baseUrl' => '@web/files',
            'buckets' => [
                'temp',
                'item',
            ]
        ],
        // ...
    ],
    // ...
];

您也可以指定一个与内部名称不同的存储桶名称。在下面的示例中,存储桶通过Wii::$app->fileStorage->getBucket('images');检索,但将存储在my-image-bucket存储桶中。

return [
    'components' => [
        'fileStorage' => [
            'class' => 'mycademy\yii2filestorage\amazon\Storage',
            'buckets' => [
                'buckets' => [
                    'images' => [
                        'name' => 'my-image-bucket',
                        'region' => 'us-west-1',
                    ],
                ],
            ]
        ],
        // ...
    ],
    // ...
];

如果需要,您还可以使用[[\mycademy\yii2filestorage\hub\Storage]]组合几个不同的存储

return [
    'components' => [
        'fileStorage' => [
            'class' => 'mycademy\yii2filestorage\hub\Storage',
            'storages' => [
                [
                    'class' => 'mycademy\yii2filestorage\sftp\Storage',
                    'ssh' => [
                        'host' => 'file.server.com',
                        'username' => 'user',
                        'password' => 'some-password',
                    ],
                    'basePath' => '/var/www/html/files',
                    'baseUrl' => 'http://file.server.com/files',
                    'buckets' => [
                        'item',
                    ]
                ],
                [
                    'class' => 'mycademy\yii2filestorage\local\Storage',
                    'basePath' => '@webroot/files',
                    'baseUrl' => '@web/files',
                    'buckets' => [
                        'temp',
                    ]
                ]
            ],
        ],
        // ...
    ],
    // ...
];

通过URL访问文件

几乎所有文件存储实现,在这个扩展中实现,都提供了通过Web URL访问存储文件的机制。实际机制实现可能因特定存储而异。例如:[[\mycademy\yii2filestorage\local\Storage]] 允许设置指向其根目录的URL,为特定文件创建URL,将文件名附加到基本URL上,而 [[\mycademy\yii2filestorage\amazon\Storage]] 使用S3内置对象URL组合。

为了获取指向存储文件的URL,您应使用 [[\mycademy\yii2filestorage\BucketInterface::getFileUrl()]] 方法

$bucket = Yii::$app->fileStorage->getBucket('tempFiles');

$fileUrl = $bucket->getFileUrl('image.jpg');

如果特定存储不支持原生的URL文件访问,或者由于某种原因不可用或不希望使用,您可以通过Yii URL路由机制设置文件URL的组成。您需要设置 baseUrl 为一个数组,包含指向将返回文件内容的Yii控制器动作的路由。例如

return [
    'components' => [
        'fileStorage' => [
            'class' => 'mycademy\yii2filestorage\local\Storage',
            'baseUrl' => ['/file/download'],
            // ...
        ],
        // ...
    ],
    // ...
];

使用此配置,getFileUrl() 方法将使用当前应用程序URL管理器来创建URL。这样做,它将把存储桶名称作为 bucket 参数,文件名作为 filename 参数。例如

use yii\helpers\Url;

$bucket = Yii::$app->fileStorage->getBucket('images');

$fileUrl = $bucket->getFileUrl('logo.png');
$manualUrl = Url::to(['/file/download', 'bucket' => 'images', 'filename' => 'logo.png']);
var_dump($fileUrl === $manualUrl); // outputs `true`

您可以将 [[\mycademy\yii2filestorage\DownloadAction]] 设置为处理文件内容Web访问。例如

class FileController extends \yii\web\Controller
{
    public function actions()
    {
        return [
            'download' => [
                'class' => 'mycademy\yii2filestorage\DownloadAction',
            ],
        ];
    }
}

提示:通常,用于文件Web访问的控制器动作比文件存储提供的原生机制慢,但是您可以在其中放入一些额外的逻辑,例如仅允许已登录用户访问文件。

处理大文件

使用 [[\mycademy\yii2filestorage\BucketInterface::saveFileContent()]] 或 [[\mycademy\yii2filestorage\BucketInterface::getFileContent()]] 等方法保存或读取大于100 MB的大文件时,可能轻易超过PHP内存限制,破坏脚本。您应使用 [[\mycademy\yii2filestorage\BucketInterface::openFile()]] 方法创建一个类似通过 [[fopen()]] PHP函数创建的文件资源。此类资源可以按块读取或写入,保持内存使用量低。例如

$bucket = Yii::$app->fileStorage->getBucket('tempFiles');

$resource = $bucket->openFile('new_file.dat', 'w');
fwrite($resource, 'content part1');
fwrite($resource, 'content part2');
// ...
fclose($resource);

$resource = $bucket->openFile('existing_file.dat', 'r');
while (!feof($resource)) {
    echo fread($resource, 1024);
}
fclose($resource);

注意:您应优先使用简单的模式如 rw,避免使用复杂的模式如 w+,因为它们可能不被某些存储支持。

日志记录

文件存储组件执行的所有文件操作都会进行日志记录。为了设置可以捕获与文件存储相关的所有条目的日志目标,您应使用类别 mycademy\yii2filestorage\*。例如

return [
    // ...
    'components' => [
        // ...
        'log' => [
            // ...
            'targets' => [
                [
                    'class' => 'yii\log\FileTarget',
                    'logFile' => '@runtime/logs/file-storage.log',
                    'categories' => ['mycademy\yii2filestorage\*'],
                ],
                // ...
            ],
        ],
    ],
];