Загрузка файлов
Загрузка файла — частая задача: обложка статьи, аватар, документ. В Yii файл принимают так же, как остальные данные формы: через модель с правилом проверки. Сам файл представляет объект класса yii\web\UploadedFile.
Модель формы
Создайте вручную файл models/UploadForm.php:
// models/UploadForm.php
namespace app\models;
use yii\base\Model;
class UploadForm extends Model
{
public $imageFile;
public function rules(): array
{
return [
['imageFile', 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg'],
];
}
}Правило file проверяет, что файл загружен и имеет разрешённое расширение. skipOnEmpty => false делает файл обязательным.
Папка для файлов
Создайте папку web/uploads. Она находится внутри корня сайта, поэтому сохранённый файл web/uploads/cover.jpg откроется по адресу /uploads/cover.jpg. У веб-сервера должно быть право записи в неё.
Действие контроллера
// controllers/PostController.php
use app\models\UploadForm;
use yii\web\UploadedFile;
public function actionUpload()
{
$model = new UploadForm();
if (Yii::$app->request->isPost) {
$model->imageFile = UploadedFile::getInstance($model, 'imageFile');
if ($model->validate()) {
$name = uniqid() . '.' . $model->imageFile->extension;
$model->imageFile->saveAs(Yii::getAlias('@webroot/uploads/') . $name);
Yii::$app->session->setFlash('success', "Файл сохранён: $name");
return $this->refresh();
}
}
return $this->render('upload', ['model' => $model]);
}UploadedFile::getInstance() достаёт файл из запроса. Метод load() для файлов не подходит. saveAs() переносит файл из временной папки в постоянную. Псевдоним @webroot означает папку web.
Шаблон формы
Создайте views/post/upload.php:
<?php
// views/post/upload.php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
<?= $form->field($model, 'imageFile')->fileInput() ?>
<?= Html::submitButton('Загрузить') ?>
<?php ActiveForm::end(); ?>Откройте /post/upload, выберите картинку и отправьте форму: появится сообщение с именем файла, а сам файл окажется в web/uploads. Если выбрать файл .txt, под полем появится ошибка о недопустимом расширении.
Свойства файла
| Свойство | Значение |
|---|---|
$file->name | Исходное имя файла на компьютере посетителя |
$file->baseName | Имя без расширения |
$file->extension | Расширение |
$file->size | Размер в байтах |
$file->type | Тип, который сообщил браузер |
Ограничения
['imageFile', 'file', 'extensions' => 'png, jpg', 'maxSize' => 2 * 1024 * 1024],maxSize ограничивает размер — здесь двумя мегабайтами. Для картинок есть правило image с параметрами maxWidth и maxHeight. PHP имеет и собственный предел — настройку upload_max_filesize в php.ini.
Частая ошибка
Без 'enctype' => 'multipart/form-data' браузер отправит только имя файла, а не его содержимое. UploadedFile::getInstance() вернёт null, и проверка сообщит, что файл не выбран. И не сохраняйте файл под исходным именем $file->name: два посетителя с файлом photo.jpg перезапишут друг друга.