2

I am developing a responsive user interface in CakePHP 4.x which occasionally uses Ajax requests. My Ajax requests are performing just fine but I am having a lot of trouble incorporating a CSV-file in the request so my controller can handle the data. What I want to accomplish is that that I can choose a CSV-file, press submit and that the Ajax-request sends the file to the controller and uses the independent rows to update the database.

My code:

Javscript:

function importProducts() {
    /* Getting form data */
    let form = document.getElementById('importProductsForm');

    let formData = new FormData();

    let file = $(form.products_file).prop('files')[0];

    formData.append("csv_file", file);

    /* Moving product stock */
    ajaxRequest('Products', 'importProducts', formData, processImportProducts);
}

function ajaxRequest(controller, action, data = null, callback = null) {
    $.ajax({
        url : "<?=$this->Url->build(['controller' => '']);?>" + "/" + controller + "/" + action,
        type : 'POST',
        data : {
            'data': data
        },
        dataType :'json',
        /*processData: false,*/
        /*contentType: false,*/
        success : function(dataArray) {    
            let response = dataArray.response;
            
            if (typeof response.data !== 'undefined') {
                data = response.data;
                
                if (callback != null) {
                    callback(data);
                }
            } else if (response.success == 0) {
                data = null;
                
                giveError(response.errorTemplate);
            } else {
                data = null;
                
                if (callback != null) {
                    callback(data);
                }
            }
        },
        error : function(request,error)
        {
            console.error(error);
        }
    });
}

At the moment the controller function does not do anything special but receiving and setting the data:

public function importProducts() {
    $this->RequestHandler->renderAs($this, 'json');

    $response = [];

    if($this->request->is('post')) {
        $data = $this->request->getData();

        $response['test'] = $data;
    } else {
        $response['success'] = 0;
    }

    $this->set(compact('response'));
    $this->viewBuilder()->setOption('serialize', true);
    $this->RequestHandler->renderAs($this, 'json');
}

After some research I discovered I could use the FormData object to send the file. The error I then received was 'illegal invocation'. After some more research I discovered this had to with automatic string parsing by Ajax. According to some other StackOverflow posts I could resolve this by setting the processdata and contenttype properties to false. This fixed the problem but resulted in an Ajax request which always would be empty (that does not contain any data). I tested this without the CSV-file with a regular data object that contains a variable with a string but also resulted in a empty request (no data send to controller).

So my problem is that without the processdata property as false I get the 'illegal invocation' error, otherwise with processdata as false I literary do not receive any data in my controller. I am looking for solution to resolve this problem so I can send my CSV-file or at least the data within the file to my controller.

Other solutions than using the FormData are also welcome, for example I tried to read the CSV-file in Javascript and turn this into another object (with the jquery csv api) to send to the controller, sadly without success until now.

Tom Dijkema
  • 33
  • 1
  • 5
  • You should take a look into https://stackoverflow.com/questions/23980733/jquery-ajax-file-upload-php Uploading files with ajax works a bit differently – Steve Kirsch May 16 '23 at 18:15

0 Answers0