File uploads in Yii2 are handled using yii\web\UploadedFile. Yii2 provides built-in support for handling file uploads using ActiveForm, Model Validations, and Controller Actions.
To handle file uploads, we need to define a model and configure rules.
UploadForm.php)namespace app\models;
use yii\base\Model;
use yii\web\UploadedFile;
class UploadForm extends Model
{
public $image; // For a single file
public $documents; // For multiple files
public function rules()
{
return [
[['image'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg, jpeg', 'maxSize' => 1024 * 1024],
[['documents'], 'file', 'extensions' => 'pdf, doc, docx', 'maxSize' => 5 * 1024 * 1024, 'maxFiles' => 5],
];
}
}'extensions' => 'png, jpg, jpeg' → Restricts file types.'maxSize' => 1024 * 1024 → Limits file size to 1MB.'maxFiles' => 5 → Allows multiple uploads.Use ActiveForm to create an upload form.
use yii\widgets\ActiveForm;
use yii\helpers\Html;
/* @var $model app\models\UploadForm */
?>
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
<?= $form->field($model, 'image')->fileInput() ?>
<?= $form->field($model, 'documents[]')->fileInput(['multiple' => true]) ?>
<?= Html::submitButton('Upload', ['class' => 'btn btn-success']) ?>
<?php ActiveForm::end(); ?>'enctype' => 'multipart/form-data' → Required for file uploads.fileInput(['multiple' => true]) → Allows multiple file uploads.Define the action to process uploaded files.
UploadController.php)namespace app\controllers;
use Yii;
use yii\web\Controller;
use yii\web\UploadedFile;
use app\models\UploadForm;
class UploadController extends Controller
{
public function actionIndex()
{
$model = new UploadForm();
if (Yii::$app->request->isPost) {
$model->image = UploadedFile::getInstance($model, 'image');
$model->documents = UploadedFile::getInstances($model, 'documents');
if ($model->validate()) {
if ($model->image) {
$imagePath = 'uploads/' . $model->image->baseName . '.' . $model->image->extension;
$model->image->saveAs($imagePath);
}
foreach ($model->documents as $document) {
$documentPath = 'uploads/' . $document->baseName . '.' . $document->extension;
$document->saveAs($documentPath);
}
Yii::$app->session->setFlash('success', 'Files uploaded successfully!');
return $this->refresh();
}
}
return $this->render('index', ['model' => $model]);
}
}UploadedFile::getInstance($model, 'image') → Retrieves single file.UploadedFile::getInstances($model, 'documents') → Retrieves multiple files.saveAs('uploads/...') → Saves files to the uploads folder.Ensure the uploads/ folder exists and is writable.
mkdir uploads
chmod 777 uploadsOnce files are uploaded, you might want to display them in a GridView.
use yii\grid\GridView;
use yii\helpers\Html;
use yii\helpers\Url;
<?= GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
'id',
[
'attribute' => 'image',
'format' => 'raw',
'value' => function ($model) {
return Html::img(Url::to('@web/uploads/' . $model->image), ['width' => '80px']);
},
],
[
'attribute' => 'document',
'format' => 'raw',
'value' => function ($model) {
return Html::a('Download', Url::to('@web/uploads/' . $model->document), ['target' => '_blank']);
},
],
],
]); ?>Instead of saving files in a directory, you can store them as binary data in MySQL.
$this->createTable('files', [
'id' => $this->primaryKey(),
'filename' => $this->string()->notNull(),
'filetype' => $this->string()->notNull(),
'filedata' => $this->binary()->notNull(),
]);FileModel.php)namespace app\models;
use yii\db\ActiveRecord;
class FileModel extends ActiveRecord
{
public static function tableName()
{
return 'files';
}
}$file = new FileModel();
$file->filename = $model->image->baseName . '.' . $model->image->extension;
$file->filetype = $model->image->type;
$file->filedata = file_get_contents($model->image->tempName);
$file->save();$file = FileModel::findOne($id);
header("Content-Type: " . $file->filetype);
echo $file->filedata;
exit;Yii2 allows creating custom file validators.
ImageSizeValidator.php)namespace app\validators;
use yii\validators\Validator;
use Yii;
class ImageSizeValidator extends Validator
{
public function validateAttribute($model, $attribute)
{
$imageInfo = getimagesize($model->$attribute->tempName);
if ($imageInfo[0] > 1000 || $imageInfo[1] > 1000) {
$this->addError($model, $attribute, 'Image size must not exceed 1000x1000 pixels.');
}
}
}public function rules()
{
return [
[['image'], ImageSizeValidator::class],
];
}Security Best Practices for File Uploads in Yii2:
'extensions' => 'png, jpg, pdf'./protected/uploads/).$filename = Yii::$app->security->generateRandomString() . '.' . $model->image->extension;web directory can be a security risk, as sensitive files might be accessible to unauthorized users.web directory is not feasible, and retrieving files can become difficult.web directory and using structured folder paths, we improve security and manageability.PhotoGalleryForm)This model handles file uploads and storage in a structured folder system.
<?php
namespace app\models\form;
use Yii;
use app\models\PhotoGallery;
use yii\base\Model;
use yii\web\UploadedFile;
class PhotoGalleryForm extends Model
{
public $label;
public $upload_image;
public $photo_gallery_model;
public function __construct(PhotoGallery $photo_gallery_model = null)
{
$this->photo_gallery_model = Yii::createObject([
'class' => PhotoGallery::className()
]);
if ($photo_gallery_model) {
$this->photo_gallery_model = $photo_gallery_model;
$this->label = $photo_gallery_model->label;
}
}
public function rules()
{
return [
[['label'], 'required'],
['label', 'string', 'max' => 255],
[['upload_image'], 'file', 'extensions' => 'jpg, jpeg, png, gif, bmp, tiff, tif, webp'],
];
}
public function attributeLabels()
{
return [
'label' => 'Photo Label',
'upload_image' => 'Upload Photo',
];
}
public function initializeForm()
{
$this->photo_gallery_model->label = $this->label;
}
public function savePhoto()
{
if ($upload_image = $this->upload_image) {
$path = Yii::$app->params['datapath'] . '/photo-gallery';
if (!file_exists($path)) {
mkdir($path, 0777, true);
}
$path .= '/' . $this->photo_gallery_model->id;
if (!file_exists($path)) {
mkdir($path, 0777, true);
}
$file_name = 'photo-gallery-' . time() . '.' . $upload_image->extension;
if ($upload_image->saveAs($path . '/' . $file_name)) {
$this->photo_gallery_model->path = $file_name;
$this->photo_gallery_model->save(false);
}
}
}
}PhotoGalleryController)This controller handles the file upload request and viewing stored images.
public function actionUpload()
{
$model = new PhotoGalleryForm();
if ($model->load(Yii::$app->request->post())) {
$model->upload_image = UploadedFile::getInstance($model, 'upload_image');
if ($model->validate()) {
$model->initializeForm();
if ($model->photo_gallery_model->save()) {
$model->savePhoto();
Yii::$app->session->setFlash('success', 'File Uploaded Successfully');
return $this->redirect(["upload"]);
}
}
}
return $this->render('upload', [
'model' => $model,
]);
}
public function actionViewimage($photo_id, $image)
{
header("Content-type: image/jpeg");
Yii::$app->response->sendFile(Yii::$app->params['datapath'] . '/photo-gallery/' . $photo_id . '/' . $image);
}params.phpDefine a secure storage path for uploaded files in the params-local.php file.
return [
'datapath' => '/var/www/html/projects/data-dynamicduniya/',
];| Problem | Solution |
|---|---|
| Files in the database make it heavy | Files are stored on the server instead of the database. |
| Web folder storage is insecure | Files are stored outside the web folder. |
Yii2 Advanced Template does not allow direct file storage in web | Uses a separate folder in datapath for secure storage. |
| Difficult to retrieve files from backend storage | A dedicated actionViewimage method retrieves files securely. |
This method ensures better security, maintainability, and compatibility with Yii2's advanced and basic templates structure.
UploadedFile.With these techniques, you can handle file uploads efficiently in Yii2!
Sign in to join the discussion and post comments.
Sign in