upload with ajax and formdata displays error

Asked

Viewed 294 times

1

I’m trying to send a file to the server with ajax and php. I’ve tried variations with people who had doubts on the same subject but nothing works (I’m sure I’m doing something stupid). I have a form with 4 fields, being one of them file type. I do all the validation and at the time of sending the error appears: "Syntaxerror: JSON.parse: Unexpected end of data at line 1 column 1 of the JSON data".

In the form I already put the attribute "enctype="Multipart/form-data".

My script is like this:

$("#formAgendaConsulta1").validate({
    // Define as regras
    unkeyup: false,
    rules:{
        arqup:{
            required: true
        },
        especialidade:{
            required: true
        },
        especialista:{
            required: true
        },
        dataConsulta:{  
            required:true, 
            dateBR:true 
        },
        horaConsulta:{ 
            required:true, 
            timeBR:true 
        }
    },
    // Define as mensagens de erro para cada regra
    messages:{
        arqup:{
            required: "Você deve selecionar o arquivo"
        },
        especialidade:{
            required: "Preenchimento obrigatório"
        },
        especialista:{
            required: "Preenchimento obrigatório"
        },
        dataConsulta:{ 
            required: "Preenchimento obrigatório", dateBR: "Data inválida" 
        },
        horaConsulta:{ 
            required: "Preenchimento obrigatório", timeBR: "Horário inválido" 
        }
    },
    submitHandler: function( form ){
        //var dados = $( form ).serialize();
        //dados.append('arqup', $('input[type=file]')[0].files[0] );
        var dados = new FormData( document.querySelector('form') );         
        //formData.append('arqup', $("input[name='arqup']").prop('files')[0]);
        //formData.append('horaConsulta', $("input[name='horaConsulta']").val());
        dados.append( 'especialidade', $("#especialidade").val() );
        dados.append( 'dataConsulta', $("#dataConsulta").val() );
        dados.append( 'horaConsulta', $("#horaConsulta").val() );
        dados.append('imagem', $('input[type=file]')[0].files[0] );
        console.log( dados );
        $.ajax({
            type: "POST",
            url: $( form ).attr('action'), // "saveAgendaConsulta1.php",  
            data: dados,
            processData: false,
            contentType: false,
            dataType: "json",
            xhr: function () {
                var myXhr = $.ajaxSettings.xhr();
                if (myXhr.upload) {
                    myXhr.upload.addEventListener('progress', function (s) {
                        console.log('PROGRESSO', s); 
                    }, false);
                }
                return myXhr;
            },
            success: function( data ){ // Executa a função se a requisição funcionar
                var msgFinal = data.msgFinal;
                $('#resultAgendaConsulta1').html( msgFinal );
                $('#resultAgendaConsulta1').show( 'slow' );
                // rolar a tela até o elemento
                //$('#cxAgendaConsulta1').animate({ scrollTop: $('#resultAgendaConsulta1').offset().top }, 'slow'); 
            },
            beforeSend: function(){ // Executa a função assim que a requisição for enviada
                $('#loadAgendaConsulta1').css({display:"block"});
            },
            complete: function(msg){ // Executa a função sempre que a requisição for executada
                $('#loadAgendaConsulta1').css({display:"none"});
            },
            error: function(){
                bootbox.alert("Falha de Conexão!<br />Não foi possível efetuar sua requisição.<br/>Aguarde alguns instantes e faça uma nova tentativa.");
            }
        });
        return false;
    }
});

2 answers

0

Sending and receiving data in AJAX is usually done using strings and you are sending the data as Object, use the function JSON.stringify() to convert the data before sending.

// ...
$.ajax({
    type: "POST",
    url: $( form ).attr('action'), // "saveAgendaConsulta1.php",  
    data: JSON.stringify(dados),
    // ...
    });

At the reception you will need to use the JSON.parse() for conversion of the received JSON (string) for a Javascript object; except if you are using jQuery and there it is possible to do it directly with $.getJSON().

  • Giovanni did as you said, but it’s still the same mistake. In the browser debug, in params, displays only the word 'JSON' (I believe no string came) and in Response displays the error already mentioned.

  • One thing I forgot, put contentType: 'application/json; charset=utf-8'to warn the other end that you are sending a JSON, maybe it will. And how you use the Formdata do not need to convert the object with JSON.stringify().

  • Then the file that receives the data was already configured as you mentioned. As for Formdata, the error is exactly msm (with or without conversion). The funny thing is that looking at the examples of the people who use Formdata, none of them do conversion and from what I’ve seen, they don’t have that kind of mistake. The jquery I am using is version: v1.11.0 and the jquery plugin is valid in version 1.11.1

  • I did a test here and noticed that Formdata objects are not sent as JSON but in a text format Content-Disposition: form-data; name="chave1" Giovanni ..., and maybe this is the error of validation of the data. You want me to edit my answer to not use Formdata?

  • Eae, Giovanni. Yes, but still the problem for uploading the file remains (input type 'file'). It’s weird why I made a mistake. By the examples I saw here on the site, the staff can send the data with Formdata without having to convert; I do not know why mine does not send. Thanks for your help!

0

Replace the excerpt from submitHandler: function( form ) { ... } for

submitHandler: function( form ) {

    // cria um objeto com os respectivos valores (ao efetuar as solicitações, será convertido)
    // "especialidade=valor&dataConsulta=###[...]""
    let obterDados = {
        "especialidade": $("#especialidade").val(),
        "dataConsulta": $("#dataConsulta").val(),
        "horaConsulta": $("#horaConsulta").val(),
        "imagem": $("input[type=file]")[0].files[0]
    };

    const frmData = new FormData();

    for (let key in obterDados)
        Array.isArray(obterDados[key])
            ? obterDados[key].forEach(value => frmData.append(`${key}[]`, value))
            : frmData.append(key, obterDados[key]); 
}

and in $.ajax({ ... }) change the data: dados for data: frmData

$.ajax({
    type: "POST",
    url: $(form).attr("action"),
    data: frmData, // todo conteúdo armazenado no FormData() inicialmente..
    processData: false,
    contentType: false,
    dataType: "json",
    xhr: function () {
        var myXhr = $.ajaxSettings.xhr();
        if (myXhr.upload) {
            myXhr.upload.addEventListener('progress', function (s) {
                console.log('PROGRESSO', s); 
            }, false);
        }
        return myXhr;
    },
})

...

This way you can send Texts and Archives and the data receiver being the may use the variable $_POST["chave-que-deseja"] and the function move_uploaded_file() to receive the respective files submitted in the form.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.