2

I'm having a terrible time trying to pass a file from a view to a controller using Ajax with CakePHP 2.10.7.

My view has the following input:

<div id="staff-bg-image-container">
   <!-- Image uploading box exists here. -->
</div>
<input type="file" id="background_image_file" name="background_image_file" style="display:none;" accept="image/png, image/jpeg">

And my JavaScript looks like this:

$('#staff-bg-image-container').on('click', () => $('#background_image_file').trigger('click') );
$('#background_image_file').on('change', upload_background);

function upload_background()
{
    var file = this.files[0];    
    data = new FormData();
    data.append('file', file);

    $.ajax({
        url: '/staff/ajaxUploadBackgroundImage',
        type: 'POST',
        data: data,
        contentType: false,
        processData: false,
        cache: false,
        success: function(res){
            console.log(res);
        },
    });
}

But when I send this request to the controller the $this->request->data array is empty. I have tried doing this using XMLHttpRequest instead of jQuery as well, but the result was the same. Why is CakePHP not recognizing the file?

Edit: I can access the file using the $_FILES globals array. However, according to the CakePHP documentation it should be present in the request data array. I would appreciate if you could tell me why it is not.

Nadav
  • 1,055
  • 1
  • 10
  • 23
  • have you added enctype='multipart/form-data' in your form? – Sehdev Feb 18 '20 at 05:37
  • @Sehdev There is no form. To my understanding it is not necessary to create a form if I need to send only one field. – Nadav Feb 18 '20 at 07:56
  • How would you perform change event when the element is not visible style="display:none;"?? – Sehdev Feb 18 '20 at 11:10
  • @Sehdev Because the example was work-related I only included the problematic part. Sorry if it wasn't clear. I have updated my question to make it less confusing. I am able to submit the request just fine. But the CakePHP request object doesn't include the posted file. – Nadav Feb 19 '20 at 00:23

1 Answers1

0

What I would do in this case, first of all you are trying to upload and save with just one onchange event. In this case, my approach would be to create a button which you would do an onclick event in order to save the image that you just uploaded. Therefore, the markup should be like this :

  <div id="staff-bg-image-container">
    <img src='/files/<?php echo $data['staff']['background_image_file']; ?>' id="bgimg" class="profile_image" width="450" alt="Image" />
 <!-- Image uploading box exists here. -->
  </div>
 <input type="file" id="background_image_file" name="background_image_file" 
   accept="image/png, image/jpeg"  onchange="readImage(this);"> 
  <button id="saveimg" style="margin-top: 10px;" class="btn-web-admin btn-save 
   upload_img"><?php echo 'Save Image'; ?>
    </button>

Your Javascript therefore should go like:

  function readImage(input) {
    if (input.files && input.files[0]) {
        var reader = new FileReader();               
        reader.onload = function (e) {
                $('#background_image_file').attr('src',e.target.result); // 
               setting ur image here
               $('#saveimg').show();        
       };
       reader.readAsDataURL(input.files[0]);   // Read in the image file as a data URL.             }             
   }
}   

   $('#saveimg').on('click', function(e){
            e.preventDefault();
            var _validFileExtensions = [".jpg", ".jpeg", ".gif", ".png"];
            var validate_img = false;
            var sFileName = $('#background_image_file').val();
            for (var j = 0; j < _validFileExtensions.length; j++){
                var sCurExtension = _validFileExtensions[j];
                if (sFileName.substr(sFileName.length - sCurExtension.length, sCurExtension.length).toLowerCase() == sCurExtension.toLowerCase()) {
                    validate_img = true;
                    break;
                }
            }

            if(validate_img){
                var data = new FormData();
                var file = $('#background_image_file')files[0].;


                data.append('file');
                $.ajax({
                    type: "POST",
                    url: "/staff/ajaxUploadBackgroundImage",
                    data: data,
                    contentType: false,
                    cache: false,
                    processData: false,
                    success: function(data) {
                        var img = new Image();

                         img.onload = function() {
                            var width = img.width;
                            var height = img.height;
                         }
                        img.src = ($('#bgimg')[0]).src;
                    },
                    error: function(a, b, c){
                        console.log('Select a valid image.');
                        console.log(a);
                        console.log(b);
                        console.log(c);
                        return false;
                    }
                });
            }else{
                console.log('Select a valid image.');
            }
    });

Also a last hint that I would give you as you are using a FormData, in your Controller instead of having a $this->request->data, I would advise you to use $this->request->form as you are supossedly uploading an image with an Ajax request.

     $dataimg = $this->request->form['file']; 
     $this->set('image', $dataimg);

I hope that can help you to get a hint of why it is not working.

Oris Sin
  • 1,023
  • 1
  • 13
  • 33