Image/file Upload In Yii2

I circumvented the problem with the following code, but I rewrite the filename in the model after


\yii\web\UploadedFile::getInstance($model, 'image');

Remains the problem of $__POST[‘Demo’][‘image’] = NULL

MyModel


public function rules() {

    return [

        [['image'], 'safe'],

        [['image'], 'file', 'types' => Yii::$app->controller->module->imagetype], // is 'jpg,jpeg,gif,png' from configuration

    ];

}

MyView


use kartik\widgets\ActiveForm;

use kartik\widgets\FileInput;


$form = ActiveForm::begin([

	'options' => ['enctype'=>'multipart/form-data'],

]);


echo $form->field($model, 'image')->widget(FileInput::classname(), [

        'options' => ['accept' => 'image/'.Yii::$app->controller->module->imagetype], // is 'jpg,jpeg,gif,png' from configuration

        'pluginOptions' => [

	    'previewFileType' => 'image',

	],

]);


echo Html::submitButton('Submit', ['class'=>'btn btn-primary']);

ActiveForm::end();



MyController


public function actionCreate()

    {

        $model = new Demo;


        if ($model->load(Yii::$app->request->post()) && $model->save()) 

		{		

			$imagepath = Yii::$app->controller->module->imagepath; // is dirname(dirname(__DIR__)) . '/frontend/web/img/' from configuration

			$this->uploadImage($model,$imagepath);

				

			Yii::$app->session->setFlash('success', \Yii::t('articles.message', 'Demo has been saved!'));

            return $this->redirect([

				'view', 'id' => $model->id,

			]);

        } else {

            return $this->render('create', [

                'model' => $model,

            ]);

        }

    }


// Upload Image in a select Folder

	protected function uploadImage($model,$imagepath)

	{

		$file = \yii\web\UploadedFile::getInstance($model, 'image');

		$file->saveAs($imagepath.$file->name);

		$model->image = $file->name;

		$model->save();

	}




Not related directly to the problem above - but in case you are using the widget to upload multiple files you should use the array input syntax for PHP to recognize the files as an array of files:




echo $form->field($model, 'filename[]') // note the brackets

    ->widget(FileInput::classname(), [

        'options'=>['multiple'=>true]

    ]);



Hi Kartik,

I’m trying to make this: when i go to an update form, automatically loading the name of the file (loaded from the database) and the preview.

How do I populate these fields? I have to run a js function? which one?

Did not get the question completely?

Loading a file from server and displaying in view would need to be done through PHP only. If I have time - I can post a wiki later telling how to do that and how you trigger update of this uploaded file.

If you are hinting, that the server file should be read by the FileInput widget… its not possible. Its one way behavior only (create new upload - not update). The FileInput widget can only select files from client for uploading to server (its based on the HTML file input only and is limited by the HTML File Input features).

The answer to my question was the second: the widget input file is one way. To bypass the problem, in the update view if the image is present in the database i will show it in the form with a button to remove it, else i show the widget to upload the file.

Thanks

That’s correct… its as simple as the following. You can just style the following img tags using additional div container and css to mimic it like the FileInput widget preview.




$imageUrl = self::getUploadedFile(); // get file if available from the db/server


$image = ($imageUrl == null) ? 

    Html::img('/images/default.png', ['alt' => 'No image yet']) :

    Html::img($imageUrl, ['alt' => 'User avatar']);


echo $image;


if ($imageUrl == null) { // to show FileInput only for new upload

    echo FileInput::widget($options);

}

else {

    echo Html::a('Remove Image', $deleteAction, ['class'=>'btn btn-danger']);

}



Just posted a wiki on using fileinput for reference.

Hello everyone.

Great widget but I have a problem with multiload.

The form`s input field:


echo '<label class="control-label">Add Attachments</label>';

        echo FileInput::widget([

            'model' => $model,

            'attribute' => 'image',

            'options' => ['multiple' => true]

        ]);

But the UploadedFile::getInstances($model, ‘image’) in the controller returns the array with only one file`s data.

It looks like:


Array

(

    [0] => yii\web\UploadedFile Object

        (

            [name] => LF4IchVSjy4.jpg

            [tempName] => /tmp/phpXsrkB0

            [type] => image/jpeg

            [size] => 58092

            [error] => 0

        )


)

What`s the problem? Does anyone know?

Thanks a lot!

Thanks read below.

In order for PHP to recognize MULTIPLE FILE INPUT, you must name the attribute in array format.




echo FileInput::widget([

    'model' => $model,

    'attribute' => 'image[]',

    'options' => ['multiple' => true]

]);



Refer this wiki I created for the same.

have anybody of you ever encountered this sort of issue on Yii 2.0 before? The validator for extensions of file doesn’t work because the function: FileHelper::getMimeType($file->tempName, null, false) return this: “inode/x-empty”, so that the validator always return false.

hi everyone

i am new yii2 frame work

my error is

Exception (Unknown Property) ‘yii\base\UnknownPropertyException’ with message ‘Setting unknown property: yii\validators\FileValidator::types’

in my model

============

<?php

namespace app\models;

use Yii;

/**

  • This is the model class for table "upload".

  • @property integer $file_id

  • @property string $image

*/

class Upload extends \yii\db\ActiveRecord

{

/**


 * @inheritdoc


 */


public static function tableName()


{


    return 'upload';


}





/**


 * @inheritdoc


 */

public function rules() {

return [


    [['image'], 'safe'],


    [['image'], 'file', 'types' =&gt; 'jpg'],


];


 }


/**


 * @inheritdoc


 */


public function attributeLabels()


{


    return [


        'file_id' =&gt; 'File ID',


        'image' =&gt; 'Image',


    ];


}

}

my view

=======

<?php

use yii\helpers\Html;

use kartik&#092;form&#092;ActiveForm;


use kartik&#092;widgets&#092;FileInput;


?&gt;

<?php $form = ActiveForm::begin([‘options’ => [‘enctype’=>‘multipart/form-data’]]);?>

<?php echo $form->field($model, ‘image’)->widget(FileInput::classname(), [

    'options' =&gt; ['accept' =&gt; 'image/*'],


]); ?&gt;

<?php echo Html::submitButton(‘Submit’, [‘class’=>‘btn btn-primary’]);?>

<?php ActiveForm::end(); ?>

my controler

==============

<?php

namespace app\controllers;

use Yii;

use app\models\Upload;

use yii\data\ActiveDataProvider;

use yii\web\Controller;

use yii\web\NotFoundHttpException;

use yii\filters\VerbFilter;

/**

  • UploadController implements the CRUD actions for Upload model.

*/

class UploadController extends Controller

{

public function behaviors()


{


    return [


        'verbs' =&gt; [


            'class' =&gt; VerbFilter::className(),


            'actions' =&gt; [


                'delete' =&gt; ['post'],


            ],


        ],


    ];


}





/**


 * Lists all Upload models.


 * @return mixed


 */


public function actionIndex()


{


    &#036;dataProvider = new ActiveDataProvider([


        'query' =&gt; Upload::find(),


    ]);





    return &#036;this-&gt;render('index', [


        'dataProvider' =&gt; &#036;dataProvider,


    ]);


}





/**


 * Displays a single Upload model.


 * @param integer &#036;id


 * @return mixed


 */


public function actionView(&#036;id)


{


    return &#036;this-&gt;render('view', [


        'model' =&gt; &#036;this-&gt;findModel(&#036;id),


    ]);


}





/**


 * Creates a new Upload model.


 * If creation is successful, the browser will be redirected to the 'view' page.


 * @return mixed


 */


public function actionCreate()


{


    &#036;model = new Upload();





    if (&#036;model-&gt;load(Yii::&#036;app-&gt;request-&gt;post()) &amp;&amp; &#036;model-&gt;save()) {


        return &#036;this-&gt;redirect(['view', 'id' =&gt; &#036;model-&gt;file_id]);


    } else {


        return &#036;this-&gt;render('create', [


            'model' =&gt; &#036;model,


        ]);


    }


}








public function actionUpload()

{

&#036;model = new Upload;


if (&#33;empty(&#036;_POST)) {


    &#036;model-&gt;image = &#036;_POST['Upload']['image'];


    &#036;file = &#092;yii&#092;web&#092;UploadedFile::getInstance(&#036;model, 'image');


    var_dump(&#036;file);





    // You can then do the following


    if (&#036;model-&gt;save()) {


        &#036;file-&gt;saveAs('path/to/file');


    }


    // its better if you relegate such a code to your model class


}


return &#036;this-&gt;render('upload', ['model'=&gt;&#036;model]);

}

/**


 * Updates an existing Upload model.


 * If update is successful, the browser will be redirected to the 'view' page.


 * @param integer &#036;id


 * @return mixed


 */


public function actionUpdate(&#036;id)


{


    &#036;model = &#036;this-&gt;findModel(&#036;id);





    if (&#036;model-&gt;load(Yii::&#036;app-&gt;request-&gt;post()) &amp;&amp; &#036;model-&gt;save()) {


        return &#036;this-&gt;redirect(['view', 'id' =&gt; &#036;model-&gt;file_id]);


    } else {


        return &#036;this-&gt;render('update', [


            'model' =&gt; &#036;model,


        ]);


    }


}





/**


 * Deletes an existing Upload model.


 * If deletion is successful, the browser will be redirected to the 'index' page.


 * @param integer &#036;id


 * @return mixed


 */


public function actionDelete(&#036;id)


{


    &#036;this-&gt;findModel(&#036;id)-&gt;delete();





    return &#036;this-&gt;redirect(['index']);


}





/**


 * Finds the Upload model based on its primary key value.


 * If the model is not found, a 404 HTTP exception will be thrown.


 * @param integer &#036;id


 * @return Upload the loaded model


 * @throws NotFoundHttpException if the model cannot be found


 */


protected function findModel(&#036;id)


{


    if ((&#036;model = Upload::findOne(&#036;id)) &#33;== null) {


        return &#036;model;


    } else {


        throw new NotFoundHttpException('The requested page does not exist.');


    }


}

}

what can i do for upload and save the file

please help me thanks in advance

To extend this I wanted to ask where the mistake is?

When I use just:


echo $form->field($model, 'image')->fileInput();

everything works properly - the image is uploaded and the old one deleted.

But not when I want to have more control:




echo $form->field($model, 'image')->widget(FileInput::className(), [

    'pluginOptions' => [

        'options'=>[

            'accept'=>'image/*',

            'multiple'=>true

        ],

        'allowedFileExtensions'=>['jpg','gif','jpeg', 'png'],

        'initialPreview'=>[

            Html::img($model->getImageUrl(), ['class'=>'file-preview-image', 'alt'=>$title, 'title'=>$title]),

        ],

        'showCaption' => false,

        'showRemove' => false,

        'showUpload' => false,

        'browseClass' => 'btn btn-grey',

        'browseIcon' => '<i class="fa fa-folder-open" style="font-weight: 600; line-height: 1.3em;"></i> ',

        'browseLabel' =>  'Profilbild'

    ],

])->label(false)



What am I doing wrong?

I had this very same issue, which was solved by me saving the .php file with encoding: "UTF-8 without BOM"

I deleted the file copied the code to sublime and saved it with encoding: "UTF-8" instead of "UTF-8 with BOM".

But nothing changed it still doesn’t work. Or isn’t it about the view instead of another file? I builded the form with gii where the upload is within.

I am sorry for mistakes.

I would like to get multiple files in controller.

If I use code in view




$form->field($model, 'attachfile[]')->fileInput(['multiple' => true])



I recieve data in my controller:




$_FILES = [

    'Message' => [

        'name' => [

            'attachfile' => [

                0 => 'conf.zip'

                1 => 'src.zip'

            ]

        ]

        'type' => [

            'attachfile' => [

                0 => 'application/octet-stream'

                1 => 'application/octet-stream'

            ]

        ]

        'tmp_name' => [

            'attachfile' => [

                0 => 'C:\\Windows\\Temp\\php13DA.tmp'

                1 => 'C:\\Windows\\Temp\\php13EA.tmp'

            ]

        ]

        'error' => [

            'attachfile' => [

                0 => 0

                1 => 0

            ]

        ]

        'size' => [

            'attachfile' => [

                0 => 90494

                1 => 4969

            ]

        ]

    ]

]



When I try to use kartik\file\FileInput widget




$form

   ->field($model, 'attachfile[]')

   ->widget(

        FileInput::classname(),

        [

            'options'=>[

                'multiple' => 'multiple'

            ],

            'pluginOptions'=>[

                'uploadUrl' => Url::to(['file/upload']),

                'allowedFileExtensions' => Yii::$app->params['message.file.ext'],

                'maxFileCount' => 3,

            ]

        ])



I recived only one file ( in screen form I select two files ):




$_FILES = [

    'Message' => [

        'name' => [

            'attachfile' => [

                0 => 'src.zip'

            ]

        ]

        'type' => [

            'attachfile' => [

                0 => 'application/octet-stream'

            ]

        ]

        'tmp_name' => [

            'attachfile' => [

                0 => 'C:\\Windows\\Temp\\phpB93F.tmp'

            ]

        ]

        'error' => [

            'attachfile' => [

                0 => 0

            ]

        ]

        'size' => [

            'attachfile' => [

                0 => 4969

            ]

        ]

    ]

]



When i try to drag and drop two files I get nothing on server:




$_FILES = [

    'Message' => [

        'name' => [

            'attachfile' => [

                0 => ''

            ]

        ]

        'type' => [

            'attachfile' => [

                0 => ''

            ]

        ]

        'tmp_name' => [

            'attachfile' => [

                0 => ''

            ]

        ]

        'error' => [

            'attachfile' => [

                0 => 4

            ]

        ]

        'size' => [

            'attachfile' => [

                0 => 0

            ]

        ]

    ]

]



What I have to do for kartik\file\FileInput widget to get all selected file in controller?

Hi, Kartik! I was looking for solution of my problem and couldn’t find it :(

I am trying to use multiple fileinput with ajax (usin uploadUrl option).

So, I can’t make my code to work correctly. All I need is:

  1. to click on "browse"-button and select several photos

or

  1. open some folder and drag&drop this files to the current field.

if 1 - I receiving array of files and it’s work’s almost correctly except one thing - if I remove some of added files before click on form-submit button I am getting empty array of files.

  1. if I drag and drop files, I am getting an empty array of files in my controller if I click on form-submit button, but if I press Upload button - action in controller getting post with files. But this way is not good for me, I will hide Upload button and gonna use only form-submit button.

So the question is: how can I tie an ajax form with form submit button? Or I only can to use fileinput without ajax drag and drop feature…

Thanks :)

same issue im facing in multiple file upload. and same in drag & drop uploading.

please guide us kartik.

regards,

webin.

I have solved it. ny way thanx all.

Describe your soloution please!

can i get the solution