This is for folks who are using \kartik\widgets\FileInput
to upload files from your client. How do you display an image for update after you have uploaded it to the server using the widget?
Understanding Basics
The FileInput widget is an enhancement of the HTML5 file input. It offers you the ability to preview your selected files from the client before it is uploaded to the server. It also supports a method to upload single or multiple files from the client to the server. However, this process occurs only one way, as this is limited by the HTML5 file input capability. Hence the file input only pushes/uploads files from client to server and not vice-versa. Therefore, it does not offer a method to fetch a preselected value from the server and display on the client. Hence, once the file is uploaded to the server, you cannot display the uploaded file directly from the file input.
Displaying Uploaded File for Update
Here are the steps for you to show the uploaded file considering a scenario for User profile image upload.
Step 1: Setup Model
You have a User
model and an attribute image_file
that stores the file name of the uploaded image file.
Step 2: Setup Upload Access Paths
You have set the images to be uploaded to a location $baseUrl/uploads
where $baseUrl
is the application baseUrl.
Step 3: Get Display Image Function
Create a simple function in your User
model like this
const IMAGE_PLACEHOLDER = '/images/default_user.jpg'; public function getDisplayImage() { if (empty($model->image_file)) { // if you do not want a placeholder $image = null; // else if you want to display a placeholder $image = Html::img(self::IMAGE_PLACEHOLDER, [ 'alt'=>Yii::t('app, 'No avatar yet'), 'title'=>Yii::t('app, 'Upload your avatar by selecting browse below'), 'class'=>'file-preview-image' // add a CSS class to make your image styling consistent ]); } else { $image = Html::img(Yii::$app->urlManager->baseUrl . '/' . $model->image_file, [ 'alt'=>Yii::t('app, 'Avatar for ') . $model->username, 'title'=>Yii::t('app, 'Click remove button below to remove this image'), 'class'=>'file-preview-image' // add a CSS class to make your image styling consistent ]); } // enclose in a container if you wish with appropriate styles return ($image == null) ? null : Html::tag('div', $image, ['class' => 'file-preview-frame']); }
Step 4: Delete Image Function
In your model write your function to delete and remove an uploaded image.
public function deleteImage() { $image = Yii::$app->basePath . '/uploads/' . $this->image_file; if (unlink($image)) { $this->image_file = null; $this->save(); return true; } return false; }
Step 5: Your view/form
Here is how you should render the view/form where you have the file input widget:
// profile.php // display your image or a placeholder first echo $model->imageDisplay; if (empty($model->image_file)) { echo $form->field($model, 'image_file')->widget(FileInput::classname(), [ 'options' => ['accept' => 'image/*'], ]); } else { echo Html::a( Yii::t('app', 'Remove Image'), Url::to['/user/deleteImage', 'id'=>$model->id], ['class' => 'btn btn-danger'] ); }
Step 6: Your controller
Include the file removal action in your controller that redirects back to the profile view above
// UserController.php // NOTE: You must set controller access rules for this action // below to allow only specific user(s) to delete the image public function actionDeleteImage($id) { $model = User::findOne($id); if ($model->deleteImage()) { Yii::$app->session->setFlash('success', 'Your image was removed successfully. Upload another by clicking Browse below'); } else { Yii::$app->session->setFlash('error', 'Error removing image. Please try again later or contact the system admin.'); } return $this->render('profile', ['model'=>$model]); }