yii2-storage A complete extension for file storage management in Yii2 that supports multiple cloud and local storage providers.

  1. Requirements
  2. Installation
  3. Configuration
  4. Configuration
  5. Usage
  6. Advanced Configuration Examples
  7. Resources

A complete extension for file storage management in Yii2 that supports multiple cloud and local storage providers.

Requirements

Yii 2.0 or above

Installation

This extension is distributed as a ZIP file that must be manually extracted.

This documentation asumes the user is familiar with AWS S3, Azure Blob Storage and/or Google Cloud Storage service(s).

Installation steps:
  1. Download the yii2-storage component ZIP file

  2. Extract to a directory of your choice within the project: components/neoacevedo/yii2-storage/

  3. Configure repository in your composer.json project: `json "repositories": [

     {
         "type": "composer",
         "url": "https://asset-packagist.org"
     },
    {
         "type": "path",
         "name": "neoacevedo/yii2-storage",
         "url": "components/neoacevedo/yii2-storage"
     }
    

    ] `

  4. Regenerate autoloader:

    • Option 1: Direct installation
composer require neoacevedo/yii2-storage
  • Option 2: Add to the require section of your composer.json project
{
    "require": {
        "neoacevedo/yii2-storage": "dev-main"
    }
}

Then run:

composer update

Configuration

$model=new User;
$model->save();

Configuration

Once the extension is installed, configure the storage component in your Yii2 application configuration file (config/web.php or common/config/main.php):

Amazon S3
'components' => [
    'storage' => [
        'class' => 'neoacevedo\yii2\storage\S3Storage',
        'accessKey' => 'YOUR_IAM_ACCESS_KEY',
        'secretAccessKey' => 'YOUR_IAM_SECRET_ACCESS_KEY',
        'bucket' => 'your-bucket-name',
        'region' => 'us-east-1', // AWS Region
        'directory' => 'uploads/', // Directory within the bucket (optional)
        'acl' => 'public-read', // File ACL (optional)
        'storageClass' => 'STANDARD', // Storage class (optional)
        'presignedUrl' => true, // Signed URLs (optional)
        'presignedUrlExpiration' => '+1 hour', // Expiration time (optional)
        'useDualStack' => false, // IPv6 support (optional)
        'cdn' => 'https://your-cdn.com', // CDN URL (optional)
        'allowedExtensions' => 'pdf,jpg,jpeg,gif,png,bmp,doc,docx,xls,xlsx'
    ],
],

For S3-compatible services (MinIO, DigitalOcean Spaces, Backblaze B2, etc.) you can specify a custom endpoint:

'endpoint' => 'digitaloceanspaces.com', // Provider endpoint (optional)
Azure Blob Storage
'components' => [
    'storage' => [
        'class' => 'neoacevedo\yii2\storage\AzureBlobStorage',
        'accountName' => 'YOUR_STORAGE_ACCOUNT_NAME',
        'accountKey' => 'YOUR_STORAGE_ACCOUNT_KEY',
        'container' => 'your-container-name',
        'directory' => 'uploads/', // Directory within the container (optional)
        'cdn' => 'https://your-cdn.azureedge.net', // CDN URL (optional)
        'hierarchicalNamespace' => false, // true for Data Lake Gen2 (optional)
        'allowedExtensions' => 'pdf,jpg,jpeg,gif,png,bmp,doc,docx,xls,xlsx'
    ],
],
Azure File Storage
'components' => [
    'storage' => [
        'class' => 'neoacevedo\yii2\storage\AzureFileStorage',
        'accountName' => 'YOUR_STORAGE_ACCOUNT_NAME',
        'accountKey' => 'YOUR_STORAGE_ACCOUNT_KEY',
        'shareName' => 'YOUR_FILE_SHARE_NAME',
        'directory' => 'uploads/', // Directory within the file share (optional)
        'cdn' => 'https://your-cdn.azureedge.net', // CDN URL (optional)
        'signatureExpiryTime' => 7200, // SAS URL expiration time in seconds (optional)
        'allowedExtensions' => 'pdf,jpg,jpeg,gif,png,bmp,doc,docx,xls,xlsx'
    ],
],
Google Cloud Storage
'components' => [
    'storage' => [
        'class' => 'neoacevedo\yii2\storage\GoogleCloudStorage',
        'projectId' => 'YOUR_PROJECT_ID',
        'bucket' => 'your-bucket-name',
        'keyFileContent' => file_get_contents('/path/to/service-account-key.json'), // JSON file content
        'directory' => 'uploads/', // Directory within the bucket (optional)
        'cdn' => 'https://your-cdn.googleusercontent.com', // CDN URL (optional)
        'presignedUrl' => true, // Signed URLs (optional)
        'presignedUrlExpiration' => 3600, // Expiration time in seconds (optional)
        'allowedExtensions' => 'pdf,jpg,jpeg,gif,png,bmp,doc,docx,xls,xlsx'
    ],
],
Local Storage
'components' => [
    'storage' => [
        'class' => 'neoacevedo\yii2\storage\LocalStorage',
        'basePath' => '@app/web/', // Base physical directory (Yii2 alias)
        'directory' => 'uploads/', // Subdirectory within basePath (optional)
        'cdn' => 'https://your-cdn.com', // CDN URL (optional)
        'allowedExtensions' => 'pdf,jpg,jpeg,gif,png,bmp,doc,docx,xls,xlsx'
    ],
],

Usage

Basic Usage with Component
<?php
// In your controller
use yii\web\UploadedFile;

public function actionUpload()
{
    $fileManager = Yii::$app->storage->getFileManager();

    if (Yii::$app->request->isPost) {
        $fileManager->uploadedFile = UploadedFile::getInstance($fileManager, 'uploadedFile');

        // save() accepts an optional subdirectory as second argument
        if ($fileManager->validate() && Yii::$app->storage->save($fileManager)) {
            // File uploaded successfully
            $fileUrl = Yii::$app->storage->getUrl(Yii::$app->storage->fileName);
            Yii::$app->session->setFlash('success', 'File uploaded successfully: ' . $fileUrl);
        } else {
            Yii::$app->session->setFlash('error', 'Error uploading file.');
        }
    }

    return $this->render('upload', ['fileManager' => $fileManager]);
}
Direct Usage without Component
<?php
use neoacevedo\yii2\storage\S3Storage;
use yii\web\UploadedFile;

public function actionUpload()
{
    $storage = new S3Storage([
        'accessKey' => 'YOUR_IAM_ACCESS_KEY',
        'secretAccessKey' => 'YOUR_IAM_SECRET_ACCESS_KEY',
        'bucket' => 'your-bucket-name',
        'region' => 'us-east-1',
        'directory' => 'uploads/',
        'allowedExtensions' => 'pdf,jpg,jpeg,gif,png,bmp'
    ]);

    $fileManager = $storage->getFileManager();
    $fileManager->uploadedFile = UploadedFile::getInstance($fileManager, 'uploadedFile');

    // save() stores the sanitized name under which the object was saved in $storage->fileName
    if ($storage->save($fileManager)) {
        return $storage->getUrl($storage->fileName);
    }

    return false;
}
Form Integration

In the Controller:

use yii\web\UploadedFile;

public function actionCreate()
{
    $model = new YourModel();
    $fileManager = Yii::$app->storage->getFileManager();

    if ($model->load(Yii::$app->request->post())) {
        $fileManager->uploadedFile = UploadedFile::getInstance($fileManager, 'uploadedFile');

        if ($fileManager->validate() && Yii::$app->storage->save($fileManager)) {
            $model->file_path = $fileManager->uploadedFile->name;
            if ($model->save()) {
                return $this->redirect(['view', 'id' => $model->id]);
            }
        }
    }

    return $this->render('create', [
        'model' => $model,
        'fileManager' => $fileManager
    ]);
}

In the View:

<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;

$form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]);
?>

<?= $form->field($model, 'name')->textInput() ?>

<?= $form->field($fileManager, 'uploadedFile')->fileInput([
    'accept' => 'image/*,.pdf,.doc,.docx',
    'class' => 'form-control'
]) ?>

<div class="form-group">
    <?= Html::submitButton('Save', ['class' => 'btn btn-success']) ?>
</div>

<?php ActiveForm::end(); ?>
Available Methods
// Get file manager
$fileManager = Yii::$app->storage->getFileManager();

// Save file. Optionally you can specify a subdirectory as second argument.
$success = Yii::$app->storage->save($fileManager);

// Get file URL
$url = Yii::$app->storage->getUrl('filename.jpg');

// Delete file
$deleted = Yii::$app->storage->delete('filename.jpg');

// List of files/directories. Optional: directory name ending with '/' to list its contents.
$files = Yii::$app->storage->list();
$files = Yii::$app->storage->list('folder/');
Usage by Provider

The following examples assume that no directory is configured. On every provider, after a successful save(), $storage->fileName contains the sanitized name under which the file was saved. If a directory is configured:

  • On S3 and local storage, getUrl() and delete() receive the path relative to the configured directory.
  • On Azure Blob Storage and Azure File Storage, getUrl() prepends the configured directory and delete() receives the full path within the container or file share (e.g. uploads/file.jpg).
  • On Google Cloud Storage, delete() and getUrl() without CDN receive the full path of the object within the bucket; getUrl() prepends the directory only when using CDN (e.g. uploads/file.jpg).
Amazon S3
use yii\web\UploadedFile;

$storage = Yii::$app->storage; // Component configured with S3Storage

$fileManager = $storage->getFileManager();
$fileManager->uploadedFile = UploadedFile::getInstance($fileManager, 'uploadedFile');

if ($storage->save($fileManager)) {
    // save() stores the sanitized name under which the object was saved in $storage->fileName
    $url = $storage->getUrl($storage->fileName); // Pre-signed or public URL
    $storage->delete($storage->fileName);
}

$files = $storage->list();           // Objects in the configured directory
$files = $storage->list('folder/');  // Objects within 'folder/'
Azure Blob Storage
use yii\web\UploadedFile;

$storage = Yii::$app->storage; // Component configured with AzureBlobStorage

$fileManager = $storage->getFileManager();
$fileManager->uploadedFile = UploadedFile::getInstance($fileManager, 'uploadedFile');

if ($storage->save($fileManager)) {
    // save() stores the sanitized name under which the blob was saved in $storage->fileName
    $url = $storage->getUrl($storage->fileName); // Public or CDN URL (prepends the configured directory)
    $storage->delete(rtrim($storage->directory, '/') . '/' . $storage->fileName); // Full blob path within the container
}

$files = $storage->list();           // Blobs in the container
$files = $storage->list('folder/');  // Blobs within 'folder/'
Azure File Storage
use yii\web\UploadedFile;

$storage = Yii::$app->storage; // Component configured with AzureFileStorage

$fileManager = $storage->getFileManager();
$fileManager->uploadedFile = UploadedFile::getInstance($fileManager, 'uploadedFile');

if ($storage->save($fileManager)) {
    // save() stores the sanitized name under which the file was saved in $storage->fileName
    $url = $storage->getUrl($storage->fileName); // Signed (SAS) or CDN URL (prepends the configured directory)
    $storage->delete(rtrim($storage->directory, '/') . '/' . $storage->fileName); // Full path within the file share
}

$files = $storage->list();           // Files in the configured directory
$files = $storage->list('folder/');  // Files within 'folder/'
Google Cloud Storage
use yii\web\UploadedFile;

$storage = Yii::$app->storage; // Component configured with GoogleCloudStorage

$fileManager = $storage->getFileManager();
$fileManager->uploadedFile = UploadedFile::getInstance($fileManager, 'uploadedFile');

if ($storage->save($fileManager)) {
    // save() stores the sanitized name under which the object was saved in $storage->fileName
    $url = $storage->getUrl($storage->fileName); // Signed or public URL (prepends the directory only with CDN)
    $storage->delete(rtrim($storage->directory, '/') . '/' . $storage->fileName); // Full object path within the bucket
}

$files = $storage->list();           // Objects in the bucket
$files = $storage->list('folder/');  // Objects within 'folder/'
Local Storage
use yii\web\UploadedFile;

$storage = Yii::$app->storage; // Component configured with LocalStorage

$fileManager = $storage->getFileManager();
$fileManager->uploadedFile = UploadedFile::getInstance($fileManager, 'uploadedFile');

if ($storage->save($fileManager)) {
    // save() stores the name under which the file was saved in $storage->fileName
    $url = $storage->getUrl($storage->fileName);
    $storage->delete($storage->fileName);
}

$files = $storage->list();           // Files in the configured directory
$files = $storage->list('folder/');  // Files within 'folder/'

Advanced Configuration Examples

Multiple Configuration
'components' => [
    'storageImages' => [
        'class' => 'neoacevedo\yii2\storage\S3Storage',
        'accessKey' => 'YOUR_ACCESS_KEY',
        'secretAccessKey' => 'YOUR_SECRET_KEY',
        'bucket' => 'images-bucket',
        'region' => 'us-east-1',
        'directory' => 'images/',
        'allowedExtensions' => 'jpg,jpeg,gif,png,bmp'
    ],
    'storageDocuments' => [
        'class' => 'neoacevedo\yii2\storage\S3Storage',
        'accessKey' => 'YOUR_ACCESS_KEY',
        'secretAccessKey' => 'YOUR_SECRET_KEY',
        'bucket' => 'documents-bucket',
        'region' => 'us-east-1',
        'directory' => 'documents/',
        'allowedExtensions' => 'pdf,doc,docx,xls,xlsx'
    ],
],

Resources