3

I want to upload file using Ajax in yii2 framework this is my code, but in controller "get Instance" return null because of serialize data; how can i do this?

This is my controller:

<?php
public function actionUpdate($id)
    {
            $model = Signature::findOne([
                'user_id' => $id,
            ]);
            if ($model->load(Yii::$app->request->post())) {
                $model->file = UploadedFile::getInstance($model, 'file');
                $model->file->saveAs('uploads/signature/' . $model->user_id . '.' . $model->file->extension);
                $model->url = 'uploads/signature/' . $model->user_id . '.' . $model->file->extension;

                if ($model->save()) {
                    echo 1;
                } else {
                    echo 0;
                    echo $model->file;
                }
            } else {
                return $this->renderAjax('update', [
                    'model' => $model,
                ]);
            }
    }
?>

This is my script code I can't get my file in controller and it return null

<?php $script = <<<JS

$('form#{$model->formName()}').on('beforeSubmit', function(e)
{
    var \$form = $(this);

    $.post(
    \$form.attr("action"),
    \$form.serialize(),

    )
        .done(function(result){
        if(result == 1)
        {
            $(document).find('#update_signature_modal').modal('hide');
            $.pjax.reload({container:'#branchesGrid'});
            //alert();
        } else {
            alert(result);
        }
        }).fail(function()
        {
            console.log("server error");
        });
        return false;
});

JS;
$this->registerJs($script);
?>
Danila Ganchar
  • 7,271
  • 11
  • 35
  • 59
Amin Shafiee
  • 366
  • 1
  • 6
  • 19

2 Answers2

6

Please refer here first

The Problem

What the problem in ajax is that $_FILES details are not sent in asynchroous request. When we submit the filled form without ajax request and debug in backend side in PHP by

echo '<pre>';
print_r($_FILES); 
print_r($_POST); 
echo '</pre>';
die; 

then we successfuly get $_FILES and $_POST data.

But when we debug the same thing in ajax request, we get only $_POST values and we get $_FILES as NULL. This led us to conclusion that $_FILES data are not sent in ajax request by our above code.

The Solution

We need to use FormData of JavaScript.

What does it do?

In simple words, it adds all necessary information of file which needs to be uploaded to data param in $.ajax OR fill up $_FILES as well as all $_POST data ie non file input such as strings number etc.

In your view file

<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
<?= $form->field($model, 'title') ?>
<?= $form->field($model, 'imageFile')->fileInput() ?>    
<button type="button" class="btn btn-success subm">Upload</button>
<?php ActiveForm::end(); ?>

<script>
$('.subm').click(function(e){
    var formData = new FormData($('form')[0]);
    console.log(formData);
    $.ajax({
        url: "some_php_file.php",  //Server script to process data
        type: 'POST',

        // Form data
        data: formData,

        beforeSend: beforeSendHandler, // its a function which you have to define

        success: function(response) {
            console.log(response);
        },

        error: function(){
            alert('ERROR at PHP side!!');
        },


        //Options to tell jQuery not to process data or worry about content-type.
        cache: false,
        contentType: false,
        processData: false
    });
});
</script>

Testing

Now make ajax request and debug in PHP code by print_r() as shown above, you will notice that $_FILES is not NULL and its contains all file (which needs to be uploaded) data. And if it is set you can upload using move_uploaded_file() funtion

So this is how you file is uploaded via Ajax.

Referece 1

Referece 2

Referece 3

Community
  • 1
  • 1
Sohel Ahmed Mesaniya
  • 3,013
  • 1
  • 19
  • 29
  • 1
    Great! You saved me hours. These magic `cache`, `contentType` and `processData` really important for this method to work. – cronfy Jun 23 '17 at 11:27
  • By adding `cache: false, contentType: false, processData: false` I am getting `PHP Notice 'yii\base\ErrorException' with message 'Undefined variable: model'` error – Moeez Aug 27 '18 at 10:50
3

Use FormData to get the instance of file/image type data

$( '#my-form' )
  .submit( function( e ) {
    $.ajax( {
      url: 'http://host.com/action/',
      type: 'POST',
      data: new FormData( this ),
      processData: false,
      contentType: false
    } );
    e.preventDefault();
  } );
Rahul Pawar
  • 855
  • 6
  • 24