0

I have a problem with file uploading using AJAX and Symfony. I'd like to allow to a user to register and choose a custom profile picture when registering. If no profile pictures are uploaded, it will set a default profile picture. The problem is that I've tried many possibilities and none of them work. I'll give you my AJAX script, my PHP function and my HTML form so that you could help me to find where is the problem.

AJAX Script and HTML form :

<div class="modal fade" tabindex="-1" role="dialog" id="registerModal">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h4 class="modal-title">Inscription</h4>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
            </div>
            <div class="modal-body" align="center">
                <form action="#" method="POST" enctype="multipart/form-data">
                    <label for="pseudo">Pseudo<a class="logout">*</a> : </label>
                    <input type="text" name="pseudo" placeholder="Pseudo" id="pseudo" required><br>
                    <label for="mail">E-mail<a class="logout">*</a> : </label>
                    <input type="text" name="mail" placeholder="E-mail" id="mail" required><br>
                    <label for="motdepasse">Mot de passe<a class="logout">*</a> : </label>
                    <input type="password" name="motdepasse" placeholder="Mot de passe" id="motdepasse" required><br>
                    <label for="checkMotdepasse">Vérifiez le mot de passe<a class="logout">*</a> : </label>
                    <input type="password" name="checkMotdepasse" placeholder="Vérifiez votre mot de passe" id="checkMotdepasse" required><br>
                    <label for="adresse">Adresse postale<a class="logout">*</a> : </label>
                    <input type="text" name="adresse" placeholder="Adresse" id="adresse" required><br>
                    <label for="numAdresse">N° adresse<a class="logout">*</a> : </label>
                    <input type="text" name="numAdresse" placeholder="N° adresse" id="numAdresse" required><br>
                    <label for="cp">Code postal<a class="logout">*</a> : </label>
                    <input type="text" name="cp" placeholder="Code postal" id="cp" required><br>
                    <label for="ville">Ville<a class="logout">*</a> : </label>
                    <input type="text" name="ville" placeholder="Ville" id="ville" required><br>
                    <label for="avatar">Avatar (2Mb max) : </label>
                    <input type="file" name="avatar" id="avatar">
                    <input type="submit" class="btn btn-primary" id="register" value="S'inscrire"/>
                </form><br>
                <div id="messageOKRegister" style="color: limegreen">Vous êtes correctement inscrit ! Vous allez être automatiquement redirigé.</div>
                <div id="messageErrorRegister" class="logout">Le formulaire n'est pas correctement rempli. Veuillez réessayer.</div>
                <p>Les champs marqués d'un <a class="logout">*</a> sont obligatoires.</p>
            </div>
        </div>
    </div>
</div>
<script src="{{ asset('js/jquery-3.5.1.min.js') }}"></script>
<script src="{{ asset('js/jquery-ui.min.js') }}"></script>
<script>

    $(document).ready(function () {
        $('#messageOKRegister').toggle(false);
        $('#messageErrorRegister').toggle(false);

        $("#register").click(function(event)
        {
            event.preventDefault();//Permet d'empêcher que la page se recharge après l'envoi du formulaire
            $.ajaxSetup({
                headers: {
                    'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                }
            });
            $.ajax({
                type: 'POST',
                url: '{{ path('checkReg') }}',
                data: {
                    pseudo: $('input#pseudo').val(),
                    mail: $('input#mail').val(),
                    motdepasse: $('input#motdepasse').val(),
                    checkMotdepasse: $('input#checkMotdepasse').val(),
                    adresse: $('input#adresse').val(),
                    numAdresse: $('input#numAdresse').val(),
                    cp: $('input#cp').val(),
                    ville: $('input#ville').val(),
                    avatar: $('input#avatar').val()
                },
                dataType: 'json',

                success: function(data)
                {
                    console.log("OK ! " + data);
                    let sound = document.createElement('audio');
                    $('#register').prop('disabled', true);
                    if(data.loginOK === true)
                    {
                        sound.setAttribute('src', 'https://themushroomkingdom.net/sounds/wav/smb/smb_1-up.wav');
                        sound.onloadeddata = function () {
                            sound.play();
                            $('#messageErrorRegister').toggle(false);
                            $('#messageOKRegister').toggle(true);
                            bounce($('#registerModal'));
                        };

                        setTimeout(function () {window.location.replace('{{ path('boutique') }}');}, 5000);
                    }
                    else
                    {
                        sound.setAttribute('src', 'https://themushroomkingdom.net/sounds/wav/smb/smb_fireworks.wav');
                        sound.onloadeddata = function() {
                            sound.play();
                            $('#messageOKRegister').toggle(false);
                            $('#messageErrorRegister').replaceWith("<div id = \"messageErrorRegister\" class = \"logout\">" + data.message + "</div>").toggle(true);
                            shake($('#registerModal'));
                            $('#register').prop('disabled', false);
                        };
                    }
                },
                error: function(data)
                {
                    console.log("Données PHP : " + data);
                    alert("Erreur détectée ! " + JSON.stringify(data));
                }
            });
        });
    });
    function shake(thing) {
        var interval = 100;
        var distance = 10;
        var times = 6;

        for (var i = 0; i < (times + 1); i++) {
            $(thing).animate({
                left:
                    (i % 2 == 0 ? distance : distance * -1)
            }, interval);
        }
        $(thing).animate({
            left: 0,
            top: 0
        }, interval);
    }
    function bounce(thing) {
        var interval = 100;
        var distance = 20;
        var times = 6;
        var damping = 0.8;

        for (var i = 0; i < (times + 1); i++) {
            var amt = Math.pow(-1, i) * distance / (i * damping);
            $(thing).animate({
                top: amt
            }, 100);
        }
        $(thing).animate({
            top: 0
        }, interval);
    }
</script>

PHP function :

/**
     * @Route("/checkReg", name="checkReg")
     */
    public function checkRegister(Request $request)//TODO vérifier les inscriptions pour éviter des renvois de formulaire en rafraichissant la page
    {
        $pseudo = $request->request->get('pseudo');
        $mail = $request->request->get('mail');
        $motdepasse = $request->request->get('motdepasse');
        $checkMotdepasse = $request->request->get('checkMotdepasse');
        $adresse = $request->request->get('adresse');
        $numAdresse = $request->request->get('numAdresse');
        $adresseComplete = ($adresse . " " . $numAdresse);
        $codePostal = $request->request->get('cp');
        $ville = $request->request->get('ville');
        $avatar = $request->files->get('avatar');
        $repoUser = $this->getDoctrine()->getRepository(Utilisateur::class);
        $pseudoDB = $repoUser->findOneBy(["pseudo" => $pseudo]);
        $mailDB = $repoUser->findOneBy(["email" => $mail]);
        $user = new Utilisateur();

        if ($pseudoDB)
        {
            return new JsonResponse(array('avatar' => $avatar, 'loginOK' => false, 'message' => "Le pseudo est déjà utilisé."));
        }
        elseif ($mailDB)
        {
            return new JsonResponse(array('avatar' => $avatar, 'loginOK' => false, 'message' => "L'e-mail est déjà utilisé."));
        }
        elseif ($motdepasse != $checkMotdepasse)
        {
            return new JsonResponse(array('avatar' => $avatar, 'loginOK' => false, 'message' => "Échec de la vérification du mot de passe."));
        }
        elseif (!is_numeric($numAdresse))
        {
            return new JsonResponse(array('avatar' => $avatar, 'loginOK' => false, 'message' => "Numéro d'adresse incorrect."));
        }
        elseif (!is_numeric($codePostal))
        {
            return new JsonResponse(array('avatar' => $avatar, 'loginOK' => false, 'message' => "Code postal incorrect."));
        }

        else
        {
            $user->setPseudo($pseudo)->setEmail($mail)->setMotDePasse($motdepasse)->setAdresse($adresseComplete)->setCodePostal((int) $codePostal)
                ->setVille($ville)->setNoteGlobaleArticleConforme(0.0)->setNoteGlobaleCommunicationVendeur(0.0)
                ->setNoteGlobaleRapiditeLivraison(0.0)->setIsAdmin(false);
            if ($avatar == "")
            {
                $user->setAvatar("/avatars/default.jpg");
            }
            else
            {
                if ($_FILES['avatar']['size'] <= 2000000)
                {
                    $infoAvatar = pathinfo($_FILES['avatar']['name']);
                    $extension = $infoAvatar['extension'];
                    $tabExtension = array('jpg', 'jpeg', 'gif', 'png');
                    if (in_array($extension, $tabExtension))
                    {
                        move_uploaded_file($_FILES['avatar']['tmp_name'], '/avatars/' . basename($_FILES['avatar']['name']));
                    }
                    $user->setAvatar("/avatars/" . basename($_FILES['avatar']['name']));
                }
                else
                {
                    return new JsonResponse(array('avatar' => $avatar, 'loginOK' => false, 'message' => "Votre avatar doit faire moins de 5Mb."));
                }
            }
            $manager = $this->getDoctrine()->getManager();
            $manager->persist($user);
            $manager->flush();
            return new JsonResponse(array('loginOK' => true));
        }
    }

If you could help me to find where is the problem, it will be wonderful ! Thank you in advance for your answers.

4
  • 1
    Does this answer your question? Upload file and JSON data in the same POST request using jquery ajax? Commented Sep 12, 2020 at 15:24
  • That seems better, but now I have a 500 error with this error message : "Warning: move_uploaded_file(/avatars/Link_Real.jpg): failed to open stream: No such file or directory (500 Internal Server Error)". I forgot to say that I'd like to move the profile picture to a specific folder and insert the path into the database (sorry for having forgotten this point). Commented Sep 13, 2020 at 12:17
  • 1
    Well, it looks like you are trying to move the file to a nonexistent destination, you are using an absolute path and not a path under the web root. Commented Sep 13, 2020 at 12:33
  • Yes, that was the problem I had ! Thank you very much for your help ! Commented Sep 13, 2020 at 17:51

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.