Yii Framework File Upload - php

I'm trying to learn how to upload an image file in Yii. I'm using this code
<?php
use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
<?= $form->field($model, 'imageFile')->fileInput() ?>
<button>Submit</button>
<?php ActiveForm::end() ?>
in ProjectFile/views/site/upload.php file.
The problem is in
<?= $form->field($model, 'imageFile')->fileInput() ?>
$model gives me a red underline. I have looked many examples and all of them wrote the like this.
What I need to do stop this problem?
Edit:
Is inside the controller/SiteController.php
// function for upload
public function actionUploadImage()
{
$model = new UploadImageForm();
if (Yii::$app->request->isPost) {
$model->imageFile = UploadedFile::getInstance($model, 'imageFile');
if ($model->upload()) {
// file is uploaded successfully
return;
}
}
return $this->render('upload', ['model' => $model]);
}
Is inside of models/UploadImageForm.php
<?php
namespace app\models;
use yii\base\Model;
use yii\web\UploadedFile;
class UploadImageForm extends \yii\base\Model
{
public $imageFile;
// gives rules of how to upload picture
public function rules(){
return [
[['imageFile'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg'],
];
}
// uploads picture
public function upload(){
if($this->validate()){
$this->imageFile->saveAs('uploads/' . $this->imageFile->baseName . '.' . $this->imageFile->extension);
}
}
}

Please make sure that model has attribute/field called "imageFile"
Check your editor do you get red line on your editor then its your editor related issue

The same happened to me, your view code is pretty fine. Mine was also the same, I made it work by using these lines in model function:
$imageFile= UploadedFile::getInstances($model, 'imageFile')[0];
$imageFile->saveAs('uploads/' . $imageFile->baseName . '.' . $imageFile->extension);
and in controller action:
$model->imageFile= UploadedFile::getInstances($model, 'imageFile')[0];

In views\upload.php the red underline is shown because the system can't find the $model. While running, program will connect $model to controller. So the red underline is not a problem for php files.

Related

Yii2 : File Input throws error after submitting form

When I click on the Signup button I receive the following error: Array to string conversion.
I think that the error occurs when I call fileInput() method but i don't know how to solve it.
This is the partial code of the view
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'password')->passwordInput() ?>
<?= $form->field($model, 'email') ?>
<?= $form->field($modelUpload, 'imageFile')->fileInput() ?>
<div class="form-group">
<?= Html::submitButton('Signup', ['class' => 'btn', 'name' => 'signup-button']) ?>
</div>
<?php ActiveForm::end(); ?>
While this is the code for the controller:
<?php
class SiteController extends Controller {
/**
* Signs user up.
*
* #return mixed
*/
public function actionSignup() {
$model = new SignupForm();
$modelUpload = new UploadForm();
if ($model->load(Yii::$app->request->post()) && $modelUpload->load(Yii::$app->request->post())) {
$modelUpload->imageFile = UploadedFile::getInstances($modelUpload, 'imageFile');
if ($user = $model->signup()) {
if (Yii::$app->getUser()->login($user) && $modelUpload->upload()) {
return $this->goHome();
}
}
}
return $this->render('signup', [
'model' => $model,
'modelUpload' => $modelUpload,
]);
}
}
This is the code of the model. It's the same of the official documentation.
<?php
class UploadForm extends Model {
/**
* #var UploadedFile
*/
public $imageFile;
public function rules() {
return [
[['imageFile'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg'],
];
}
public function upload() {
if ($this->validate()) {
$this->imageFile->saveAs('uploads/' . $this->imageFile->baseName . '.' . $this->imageFile->extension);
return true;
} else {
return false;
}
}
}
?>
Errors:
Instant Solution
Change your line inside the actionSignup() from below
UploadedFile::getInstances($modelUpload, 'imageFile');
to
UploadedFile::getInstance($modelUpload, 'imageFile');
Reason
It's only a single file you are uploading not multiple files so getInstances() should be getInstance()
About
getInstance : Returns an uploaded file for the given model
attribute. The file should be uploaded using
[[\yii\widgets\ActiveField::fileInput()]]
getInstances: Returns all uploaded files for the given model
attribute.
if you want to upload multiple files - having'maxFiles' > 1 in your model's FileValidator rules - change your attribute name from:
<?= $form->field($modelUpload, 'imageFile')->fileInput() ?>
to
<?= $form->field($modelUpload, 'imageFile[]')->fileInput() ?>
read this:
https://www.yiiframework.com/doc/guide/2.0/en/input-file-upload#uploading-multiple-files

image is not uploading in YII ActiveForm

I am new to Yii. I am using this code
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
<?= $form->field($model, 'description')->textarea(['rows' => 6]) ?>
<?= $form->field($model, 'image')->fileInput(['type' => 'file']) ?>
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
When i try to print post data in my controller then image field is going blank;
If i print through $_FILES then file data is showing.
Please let me know how to get image in post method.
Step 1 :
In your model file define one variable.
public $uploadedImage;
Step 2 :
In your controller,
$model->uploadedImage = UploadedFile::getInstance($model, 'image');
$model->image = $model->uploadedImage->name;
After save() method write this to store image
$model->uploadedImage->saveAs('YOUR_WEBDIR_IMAGES_FOLDER/' . $model->uploadedImage->baseName . '.' . $model->uploadedImage->extension);
[If the above solution doesn't work then try this. :
Define another variable.
public $tempVarforImage;
In your controller
$model->tempVarforImage = $model->uploadedImage->name;
$model->image = $model->tempVarforImage;
(Because once I faced the issue in confliction of 'image' field from database and yii2 based 'image' variable)]
Create UploadForm model
namespace app\models;
use yii\base\Model;
use yii\web\UploadedFile;
class UploadForm extends Model{
public $image;// Image name
public function rules()
{
return [
[['image'], 'file'/* , 'skipOnEmpty' => false *//* , 'extensions' => 'png, jpg' */],
];
}
public function upload($fileName)
{
if ($this->validate()) {
$this->image->saveAs($fileName);
return true;
} else {
return false;
}
}
}
Controller code
Add at top of your file
use app\models\UploadForm;
use yii\web\UploadedFile;
Add this in your function
$model = User();
if ($model->load(Yii::$app->request->post())) {
$model1 = new UploadForm();
$model1->image = UploadedFile::getInstance($model, 'image');
$fileName = $model1->image->baseName.'_'.time();
$extension = $model1->image->extension;
$fileName = $fileName.'.'.$extension;
$filePath = WEBSITE_SLIDER_ROOT_PATH.$fileName;
if ($model1->upload($filePath)) {
//Save in database
}
}

Yii file field posting empty values

I am a newbie in Yii, and I am trying to make an upload form in Yii, Please i need help.
Once the form post data to the controller every other post value is posted except for the file value.
i even tried checking for Errors with var_dump($model->image); and it returned this Error string '' (length=0) specifying an empty string like an image wasn't even posted at all.
This is my controller
class TestController extends Controller
{
public function actionIndex()
{
$model=new Test;
if(isset($_POST['Test']))
{
$model->attributes=$_POST['Test'];
if($model->save()){
var_dump($model->getErrors());
if ($model->image){
var_dump($model->image);
$uploadedFile=CUploadedFile::getInstance($model,'image');
$fileName = date("Y_m_d_H_i_s").$uploadedFile;
$model->image = $fileName;
if(!empty($uploadedFile)) // check if uploaded file is set or not
{
$uploadedFile->saveAs(Yii::getPathOfAlias('webroot').'/imagefolder/'.$fileName);
}
}
}
}
}
}
And this is my View
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'test-form',
'htmlOptions' => array('enctype' => 'multipart/form-data'),
'enableAjaxValidation'=>false,
)); ?>
<?php echo CHtml::activeFileField($model,'image',array('id'=>'primaryupload')); ?>
<?php echo CHtml::submitButton($model->isNewRecord ? 'UPLOAD' : 'UPLOAD',array('id'=>'submit','class'=>'btn')); ?>
<?php $this->endWidget(); ?>
Any help will be appreciated. Because i am really frusrated at this point.
If you are only new to Yii and not in PHP, than you may know that uploaded files goes via $_FILES global variable and not via $_POST global variable. So to get uploaded file, you use
$uploadedFile = CUploadedFile::getInstance($model, 'image');
So your final code looks like this:
$post = Yii::app()->request->getPost('Test');
if ($post) {
$model->attributes = $post;
$uploadedFile = CUploadedFile::getInstance($model, 'image');
if ($uploadedFile) {
$imageName = date("Y_m_d_H_i_s").$uploadedFile->name;
$model->image = $imageName;
if ($model->save()) {
$uploadedFile->saveAs(Yii::getPathOfAlias('webroot').'/imagefolder/'.$imageName );
}
}
I think you should use $_FILES['image'] instead of $model->image.
As an option, you can "hardcode" file attribute in your form. Just:
<input type="file" id="yourid" name="yourname" />
Then in YourController, where you are parsing your POST data you could directly access to $_FILES['yourname'].
Not an elegant way, but simple and fast.
P.S.: if you are using $this->beginWidget in your view, then you should add to parameters
$this->beginWidget('CActiveForm', array(
...
'htmlOptions'=>array(
'enctype'=>'multipart/form-data'
),
));

Upload pictures from Yii showing endWiget() error

Hi I also had a problem when try to upload picture using this method.
My Action/model:
class Image extends CActiveRecord
{
public $foto;
...
public function rules()
{
return array(
...
array('foto', 'file', 'types'=>'jpg, gif, png'),
...
);
}
}
My Controller:
class ImageController extends Controller
{
public function actionCreate()
{
$model=new Image;
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST['Image']))
{
$model->attributes=$_POST['Image'];
$model->image=CUploadedFile::getInstance($model,'foto');
if($model->save())
$model->foto->saveAs('productimages');
$this->redirect(array('view','id'=>$model->id));
}
$this->render('create',array(
'model'=>$model,
));
}
}
My view:
<?php $form = $this->beginWidget(
'CActiveForm',
array(
'id' => 'upload-form',
'enableAjaxValidation' => false,
'htmlOptions' => array('enctype' => 'multipart/form-data'),
)
); ?>
<?php echo $form->labelEx($model, 'foto'); ?>
<?php echo $form->fileField($model, 'foto'); ?>
<?php echo $form->error($model, 'foto'); ?>
...
<div class="row buttons">
<?php echo CHtml::submitButton('Submit'); ?>
</div>
<?php $this->endWidget(); ?>
But when I run, two problems appeared:
Problem #1:
endWiget() call [SOLVED by Ivan Misic]
ImageController contains improperly nested widget tags in its view "/var/www/html/onlineshop-nimalogos/protected/views/image/_form.php". A CActiveForm widget does not have an endWidget() call.
Problem#2:
Since problem # 1 is solved, came with another problem, the image is not saving at my 'productimages' folder.
Please help me with the problem # 2. Many thanks..
You have somewhere opened redundant CActiveForm widget and you should look into views and partials.
Yii is generting three view files with gii, and these are:
create.php update.php
| |
| |
+-------+-------+
|
|
_form.php
create and update views are rendering the same partial _form, so you should look in all three to find redundant beginWidget call.
The view you supported in your question should be _form.php partial view.

How to upload a file to directory in yii2?

i have an ActiveForm, and i want to add a field where the user can upload their photos.
the problem is that i don't have an attribute for the image in the users table and every
input field in 'yii' expects a model and an attribute as follows.
<?= $form->field($model, 'attribute')->input($platforms) ?>
i don't want to assign the image to any record nor i want to insert in in the database, i want it to be uploaded to a specific folder.
i have also checked the library kartik wrote, but also requires an attribute field.
Follow the official documentation
https://github.com/yiisoft/yii2/blob/master/docs/guide/input-file-upload.md
Form Model
namespace app\models;
use yii\base\Model;
use yii\web\UploadedFile;
/**
* UploadForm is the model behind the upload form.
*/
class UploadForm extends Model
{
/**
* #var UploadedFile|Null file attribute
*/
public $file;
/**
* #return array the validation rules.
*/
public function rules()
{
return [
[['file'], 'file'],
];
}
}
?>
Form View
<?php
use yii\widgets\ActiveForm;
$form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
<?= $form->field($model, 'file')->fileInput() ?>
<button>Submit</button>
<?php ActiveForm::end(); ?>
Controller
Now create the controller that connects form and model together:
<?php
namespace app\controllers;
use Yii;
use yii\web\Controller;
use app\models\UploadForm;
use yii\web\UploadedFile;
class SiteController extends Controller
{
public function actionUpload()
{
$model = new UploadForm();
if (Yii::$app->request->isPost) {
$model->file = UploadedFile::getInstance($model, 'file');
if ($model->validate()) {
$model->file->saveAs('uploads/' . $model->file->baseName . '.' . $model->file->extension);
}
}
return $this->render('upload', ['model' => $model]);
}
}
?>
Instead of model->load(...) we are using UploadedFile::getInstance(...). [[\yii\web\UploadedFile|UploadedFile]] does not run the model validation. It only provides information about the uploaded file. Therefore, you need to run validation manually via $model->validate(). This triggers the [[yii\validators\FileValidator|FileValidator]] that expects a file:
$file instanceof UploadedFile || $file->error == UPLOAD_ERR_NO_FILE //in code framework
If validation is successful, then we're saving the file:
$model->file->saveAs('uploads/' . $model->file->baseName . '.' . $model->file->extension);
If you're using "basic" application template then folder uploads should be created under web.
That's it. Load the page and try uploading. Uplaods should end up in basic/web/uploads.
in your view
use kartik\widgets\ActiveForm;
use kartik\widgets\FileInput;
$form = ActiveForm::begin(['options' => ['enctype'=>'multipart/form-data']]); //important
echo FileInput::widget([
'name' => 'filename',
'showUpload' => false,
'buttonOptions' => ['label' => false],
'removeOptions' => ['label' => false],
'groupOptions' => ['class' => 'input-group-lg']
]);
echo Html::submitButton('Submit', ['class'=>'btn btn-primary']);
ActiveForm::end();
in your controller
$file = \yii\web\UploadedFile::getInstanceByName('filename');
$file->saveAs('/your/directory/'.$file->name);
Create a read only attribute for your model like public $imageand proceed like
<?= $form->field($model, 'image')->fileInput() ?>
I really like Yii2 Dropzone.
Installation:
composer require --prefer-dist perminder-klair/yii2-dropzone "dev-master"
Usage:
<?php
echo \kato\DropZone::widget([
'options' => [
'url'=> Url::to(['resource-manager/upload']),
'paramName'=>'image',
'maxFilesize' => '10',
],
'clientEvents' => [
'complete' => "function(file){console.log(file)}",
'removedfile' => "function(file){alert(file.name + ' is removed')}"
],
]);
?>
Controller:
public function actionUpload(){
$model = new ResourceManager();
$uploadPath = Yii::getAlias('#root') .'/uploads/';
if (isset($_FILES['image'])) {
$file = \yii\web\UploadedFile::getInstanceByName('image');
$original_name = $file->baseName;
$newFileName = \Yii::$app->security
->generateRandomString().'.'.$file->extension;
// you can write save code here before uploading.
if ($file->saveAs($uploadPath . '/' . $newFileName)) {
$model->image = $newFileName;
$model->original_name = $original_name;
if($model->save(false)){
echo \yii\helpers\Json::encode($file);
}
else{
echo \yii\helpers\Json::encode($model->getErrors());
}
}
}
else {
return $this->render('upload', [
'model' => $model,
]);
}
return false;
}
give this code after your uploaded code
//save the path in DB..
$model->file = 'uploads/'.$imageName.'.'.$model->file->extension;
$model->save();
If you have more than one file while uploading you must use foreach for that. And you should actual name of file in a column in table and a encrypted value of that name has to be stored to avoid duplicated in the directory.. Something like this..
$userdocs->document_name = UploadedFile::getInstances($userdocs, 'document_name');
foreach ($userdocs->document_name as $key => $file) {
$img_name = Yii::$app->security->generateRandomString();
$file->saveAs('user/business_files/' . $img_name . '.' . $file->extension);
$images = $img_name . '.' . $file->extension;
$userdocs->actual_name = $file->name;
$userdocs->user_id = $user->id;
$userdocs->document_name = $images;
$userdocs->save(false);
$userdocs = new UserDocs();
}
Here a random string is generated and it will be assign with the name of the document, and it will be stored in the table. The UserDocs is the model name.

Categories