The League Flysystem for local and remote filesystems library for Yii2.
This extension provides Flysystem 3 integration for the Yii framework. Flysystem is a filesystem abstraction which allows you to easily swap out a local filesystem for a remote one.
Yii2 Flysystem uses league/flysystem
- Yii2 Flysystem
- Table of Contents
- Instalation
- Dependencies
- Dev. Dependencies
- Configuration
- Additional Configuration
- Usage
- Writing or Updating Files
- Reading Files
- Checking if a File Exists
- Deleting Files
- Getting Files Mime Type
- Getting Files Timestamp / Last Modified
- Getting Files Size
- Creating Directories
- Checking if a Directory Exists
- Deleting Directories
- Checking if a File or Directory Exists
- Managing Visibility
- Listing contents
- Copy Files or Directories
- Move Files or Directories
- Get URL Files
- Get URL Temporary Files / Presigned URL
- Get MD5 Hash File Contents
- Using Traits
Package is available on Packagist, you can install it using Composer.
composer require diecoding/yii2-flysystem "^1.0"
or add to the require section of your composer.json
file.
"diecoding/yii2-flysystem": "^1.0"
- league/flysystem-async-aws-s3
- league/flysystem-aws-s3-v3
- league/flysystem-google-cloud-storage
- league/flysystem-ftp
- league/flysystem-sftp-v3
- league/flysystem-webdav
- league/flysystem-ziparchive
- masbug/flysystem-google-drive-ext
Configure application components
as follows
return [
// ...
'components' => [
// ...
'fs' => [
'class' => \diecoding\flysystem\LocalComponent::class,
'path' => dirname(dirname(__DIR__)) . '/storage', // or you can use @alias
'secret' => 'my-secret', // for secure route url
// 'action' => '/site/file', // action route
// 'prefix' => '',
],
],
];
See: league/flysystem-async-aws-s3
Either run
composer require league/flysystem-async-aws-s3:^3.0
or add
"league/flysystem-async-aws-s3": "^3.0"
to the require
section of your composer.json
file and configure application components
as follows
return [
// ...
'components' => [
// ...
'fs' => [
'class' => \diecoding\flysystem\AsyncAwsS3Component::class,
'endpoint' => 'http://your-endpoint',
'bucket' => 'my-bucket',
'accessKeyId' => 'my-key',
'accessKeySecret' => 'my-secret',
// 'sharedCredentialsFile' => '~/.aws/credentials',
// 'sharedConfigFile' => '~/.aws/config',
// 'region' => 'us-east-1',
// 'endpointDiscoveryEnabled' => false,
// 'pathStyleEndpoint' => false,
// 'sendChunkedBody' => false,
// 'debug' => false,
// 'prefix' => '',
],
],
];
See: league/flysystem-aws-s3-v3
Either run
composer require league/flysystem-aws-s3-v3:^3.0
or add
"league/flysystem-aws-s3-v3": "^3.0"
to the require
section of your composer.json
file and configure application components
as follows
return [
// ...
'components' => [
// ...
'fs' => [
'class' => \diecoding\flysystem\AwsS3Component::class,
'endpoint' => 'http://your-endpoint',
'key' => 'your-key',
'secret' => 'your-secret',
'bucket' => 'your-bucket',
// 'region' => 'us-east-1',
// 'version' => 'latest',
// 'usePathStyleEndpoint' => false,
// 'streamReads' => false,
// 'options' => [],
// 'credentials' => [],
// 'debug' => false,
// 'prefix' => '',
],
],
];
See: league/flysystem-google-cloud-storage
Either run
composer require league/flysystem-google-cloud-storage:^3.0
or add
"league/flysystem-google-cloud-storage": "^3.0"
to the require
section of your composer.json
file and configure application components
as follows
return [
// ...
'components' => [
// ...
'fs' => [
'class' => \diecoding\flysystem\GoogleCloudStorageComponent::class,
'bucket' => 'your-bucket',
// 'apiEndpoint' => '',
// 'projectId' => '',
// 'authCache' => null,
// 'authCacheOptions' => [],
// 'authHttpHandler' => function () {},
// 'credentialsFetcher' => null,
// 'httpHandler' => function () {},
// 'keyFile' => '',
'keyFilePath' => __DIR__ . '/gcs_credentials.json',
// 'requestTimeout' => 0,
// 'retries' => 0,
// 'scopes' => [],
// 'quotaProject' => '',
// 'userProject' => false,
// 'prefix' => '',
],
],
];
See: league/flysystem-ftp
Either run
composer require league/flysystem-ftp:^3.0
or add
"league/flysystem-ftp": "^3.0"
to the require
section of your composer.json
file and configure application components
as follows
return [
// ...
'components' => [
// ...
'fs' => [
'class' => \diecoding\flysystem\FtpComponent::class,
'host' => 'hostname',
'root' => '/root/path/', // or you can use @alias
'username' => 'username',
'password' => 'password',
// 'port' => 21,
// 'ssl' => false,
// 'timeout' => 90,
// 'utf8' => false,
// 'passive' => true,
// 'transferMode' => FTP_BINARY,
// 'systemType' => null, // 'windows' or 'unix'
// 'ignorePassiveAddress' => null, // true or false
// 'timestampsOnUnixListingsEnabled' => false,
// 'recurseManually' => true,
// 'useRawListOptions' => null, // true or false
// 'passphrase' => 'secret', // for secure route url
// 'action' => '/site/file', // action route
// 'prefix' => '',
],
],
];
Either run
composer require league/flysystem-sftp-v3:^3.0
or add
"league/flysystem-sftp-v3": "^3.0"
to the require
section of your composer.json
file and configure application components
as follows
return [
// ...
'components' => [
'fs' => [
'class' => \diecoding\flysystem\SftpComponent::class,
'host' => 'hostname',
'username' => 'username',
'password' => null, // password (optional, default: null) set to null if privateKey is used
// 'privateKey' => '/path/to/my/private_key', // private key (optional, default: null) can be used instead of password, set to null if password is set
// 'passphrase' => 'super-secret-password', // passphrase (optional, default: null), set to null if privateKey is not used or has no passphrase
// 'port' => 22,
// 'useAgent' => true,
// 'timeout' => 10,
// 'maxTries' => 4,
// 'hostFingerprint' => null,
// 'connectivityChecker' => null, // connectivity checker (must be an implementation of `League\Flysystem\PhpseclibV2\ConnectivityChecker` to check if a connection can be established (optional, omit if you don't need some special handling for setting reliable connections)
// 'preferredAlgorithms' => [],
// 'root' => '/root/path/', // or you can use @alias
// 'action' => '/site/file', // action route
// 'prefix' => '',
],
],
];
Either run
composer require league/flysystem-webdav:^3.0
or add
"league/flysystem-webdav": "^3.0"
to the require
section of your composer.json
file and configure application components
as follows
return [
// ...
'components' => [
// ...
'fs' => [
'class' => \diecoding\flysystem\WebDavComponent::class,
'baseUri' => 'http://your-webdav-server.org/',
'userName' => 'your_user',
'password' => 'superSecret1234',
// 'proxy' => '',
// 'authType' => \Sabre\DAV\Client::AUTH_BASIC,
// 'encoding' => \Sabre\DAV\Client::ENCODING_IDENTITY,
// 'prefix' => '',
],
],
];
See: league/flysystem-ziparchive
Either run
composer require league/flysystem-ziparchive:^3.0
or add
"league/flysystem-ziparchive": "^3.0"
to the require
section of your composer.json
file and configure application components
as follows
return [
// ...
'components' => [
// ...
'fs' => [
'class' => \diecoding\flysystem\ZipArchiveComponent::class,
'pathToZip' => dirname(dirname(__DIR__)) . '/storage.zip', // or you can use @alias
'secret' => 'my-secret', // for secure route url
// 'action' => '/site/file', // action route
// 'prefix' => '', // root directory inside zip file
],
],
];
See: masbug/flysystem-google-drive-ext
Either run
composer require masbug/flysystem-google-drive-ext:^2.0
or add
"masbug/flysystem-google-drive-ext": "^2.0"
to the require
section of your composer.json
file and configure application components
as follows
return [
// ...
'components' => [
// ...
'fs' => [
'class' => \diecoding\flysystem\GoogleDriveComponent::class,
'applicationName' => 'My Google Drive App',
'clientId' => '',
'clientSecret' => '',
'refreshToken' => '',
// 'teamDriveId' => '',
// 'sharedFolderId' => '',
// 'options' => [],
'secret' => 'my-secret', // for secure route url
// 'action' => '/site/file', // action route
// 'prefix' => '',
],
],
];
The following adapters have URL File Action generation capabilities:
- Local Component
- FTP Component
- SFTP Component
- Google Drive Component
Configure action
in controller
as follows
This example at
SiteController
for/site/file
class SiteController extends Controller
{
//...
public function actions()
{
return [
// ...
'file' => [
'class' => \diecoding\flysystem\actions\FileAction::class,
// 'component' => 'fs',
],
];
}
}
Remember to configure
action
key infs
application components as follows
return [
// ...
'components' => [
// ...
'fs' => [
// ...
'action' => '/site/file', // action for get url file
],
],
];
Configure fs
application component as follows
return [
//...
'components' => [
//...
'fs' => [
//...
'config' => [
'visibility' => \League\Flysystem\Visibility::PRIVATE,
],
],
],
];
To write or update file
Yii::$app->fs->write('filename.ext', 'contents');
To write or update file using stream contents
$stream = fopen('/path/to/somefile.ext', 'r+');
Yii::$app->fs->writeStream('filename.ext', $stream);
To read file
$contents = Yii::$app->fs->read('filename.ext');
To retrieve a read-stream
$stream = Yii::$app->fs->readStream('filename.ext');
$contents = stream_get_contents($stream);
fclose($stream);
To check if a file exists
$exists = Yii::$app->fs->fileExists('filename.ext');
To delete file
Yii::$app->fs->delete('filename.ext');
To get file mime type
$mimeType = Yii::$app->fs->mimeType('filename.ext');
To get file timestamp
$timestamp = Yii::$app->fs->lastModified('filename.ext');
To get file size
$byte = Yii::$app->fs->fileSize('filename.ext');
To create directory
Yii::$app->fs->createDirectory('path/to/directory');
Directories are also made implicitly when writing to a deeper path
Yii::$app->fs->write('path/to/filename.ext');
To check if a directory exists
$exists = Yii::$app->fs->directoryExists('path/to/directory');
To delete directory
Yii::$app->fs->deleteDirectory('path/to/directory');
To check if a file or directory exists
$exists = Yii::$app->fs->has('path/to/directory/filename.ext');
Visibility is the abstraction of file permissions across multiple platforms. Visibility can be either public or private.
Yii::$app->fs->write('filename.ext', 'contents', [
'visibility' => \League\Flysystem\Visibility::PRIVATE
]);
You can also change and check visibility of existing files
if (Yii::$app->fs->visibility('filename.ext') === \League\Flysystem\Visibility::PRIVATE) {
Yii::$app->fs->setVisibility('filename.ext', \League\Flysystem\Visibility::PUBLIC);
}
To list contents
$contents = Yii::$app->fs->listContents();
foreach ($contents as $object) {
echo $object['basename']
. ' is located at' . $object['path']
. ' and is a ' . $object['type'];
}
By default Flysystem lists the top directory non-recursively. You can supply a directory name and recursive boolean to get more precise results
$contents = Yii::$app->fs->listContents('path/to/directory', true);
To copy contents
Yii::$app->fs->copy('path/from/directory/filename.ext', 'path/to/directory/filename.ext', [
'visibility' => \League\Flysystem\Visibility::PRIVATE
]);
To move contents
Yii::$app->fs->move('path/from/directory/filename.ext', 'path/to/directory/filename.ext', [
'visibility' => \League\Flysystem\Visibility::PRIVATE
]);
To get url contents
Yii::$app->fs->publicUrl('path/to/directory/filename.ext');
To get temporary url contents
$expiresAt = new \DateTimeImmutable('+10 Minutes');
Yii::$app->fs->temporaryUrl('path/to/directory/filename.ext', $expiresAt);
The $expiresAt
should be a valid and instance of PHP DateTimeInterface
. Read PHP documentation for details.
To get MD5 hash of the file contents
Yii::$app->fs->checksum('path/to/directory/filename.ext');
Attach the Trait to the Model/ActiveRecord
with some media attribute that will be saved in Flysystem (fs):
/**
* @property string|null $file
*/
class Model extends \yii\db\ActiveRecord
{
use \diecoding\flysystem\traits\ModelTrait;
// ...
public function rules()
{
return [
['image', 'string'], // Stores the filename
];
}
/**
* @inheritdoc
*/
protected function attributePaths()
{
return [
'image' => 'images/'
];
}
// ...
}
Override the attributePaths()
method to change the base path where the files will be saved on Flysystem (fs).
- You can map a different path to each file attribute of your
Model/ActiveRecord
.
$image = \yii\web\UploadedFile::getInstance($model, 'image');
// Save image_thumb.* to Flysystem (fs) on //my_bucket/images/ path
// The extension of the file will be determined by the submitted file type
// This allows multiple file types upload (png,jpg,gif,...)
// $model->image will hold "image_thumb.png" after this call finish with success
$model->saveUploadedFile($image, 'image', 'image_thumb');
$model->save();
// Save image_thumb.png to Flysystem (fs) on //my_bucket/images/ path
// The extension of the file will be determined by the submitted file type
// This force the extension to *.png
$model->saveUploadedFile($image, 'image', 'image_thumb.png', false);
$model->save();
// Remove the file with named saved on the image attribute
// Continuing the example, here "//my_bucket/images/my_image.png" will be deleted from Flysystem (fs)
$model->removeFile('image');
$model->save();
// Get the URL to the image on Flysystem (fs)
$model->getFileUrl('image');
// Get the presigned URL to the image on Flysystem (fs)
// The default duration is "+5 Minutes"
$model->getFilePresignedUrl('image');
The Flysystem (fs) MediaTrait depends on this component to be configured. The default configuration is to use this component on index 'fs'
, but you may use another value. For this cases, override the getFsComponent()
method:
public function getFsComponent()
{
return Yii::$app->get('my_fs_component');
}
The main method to override is attributePaths()
, which defines a path in Flysystem (fs) for each attribute of yout model. Allowing you to save each attribute in a different Flysystem (fs) folder.
Here an example:
protected function attributePaths()
{
return [
'logo' => 'logos/',
'badge' => 'images/badges/'
];
}
// or use another attribute, example: id
// ! Note: id must contain a value first if you don't want it to be empty
protected function attributePaths()
{
return [
'logo' => 'thumbnail/' . $this->id . '/logos/',
'badge' => 'thumbnail/' . $this->id . '/images/badges/'
];
}
The default pressigned URL duration is set to "+5 Minutes", override this method and use your own expiration.
Return must instance of DateTimeInterface
protected function getPresignedUrlDuration($attribute)
{
return new \DateTimeImmutable('+2 Hours');
}
// or if you want to set the attribute differently
protected function getPresignedUrlDuration($attribute)
{
switch ($attribute) {
case 'badge':
return new \DateTimeImmutable('+2 Hours');
break;
default:
return new \DateTimeImmutable('+1 Days');
break;
}
}
The value should be a valid and instance of PHP DateTimeInterface
. Read PHP documentation for details.
Read more docs: https://sugengsulistiyawan.my.id/docs/opensource/yii2/flysystem/