Partage
  • Partager sur Facebook
  • Partager sur Twitter

Ajax Upload image + affichage

Sujet résolu
    8 juin 2021 à 12:07:28

    Bonjour à tous,

    Je suis actuellement en train de faire un formulaire d'upload d'image en ajax. Mon but est donc d'upload une image puis qu'elle soit affiché directement après !

    Pour la partie upload, j'ai réussi j'arrive bien à upload mon image et la déplacer dans le dossier souhaité.

    Mon problème est pour le return de la fonction AJAX je suis à chaque fois dans le error:function() sans trop comprendre pourquoi même si j'ai cru comprendre que c'était surement à cause de mon return du script php qui est mal fait.

    Voici mon form HTML:

    <form id="update_bandeau" enctype="multipart/form-data">
    <input class="center-block btn-info" name="bandeau" type="file" style="margin-bottom:10px;" accept="image/*" required/>
    <input name="id" type="hidden" value="'+result.user.id+'">
    <button id="submit_bandeau" type="submit" name="submit" class="btn btn-success center-block">Importer un nouveau bandeau pour l\'utilisateur</button>
    </form>

    Voici mon appel AJAX:

    $(document).on('submit', '#update_bandeau', function(event){ 
        event.preventDefault();
        $.ajax({
            type: 'POST',
            async: false,  
            data: new FormData(this), 
            contentType: false,
            processData: false,
            cache: false,
            url: Routing.generate('update_bandeau'),
            success:function(data){
                console.log('result okay');
                console.log(data);
                //$('#bandeau_admin').html(file);
            },
            error:function(){
                console.log('error');
            }
        });
    });

    Voici mon script PHP:

        /**
         * @Route("/update_bandeau", name="update_bandeau", options={"expose"=true})
         */
        public function update_bandeau(Request $request)
        {
            try{
                if ($request->isXmlHttpRequest()) {
                    $em = $this->getDoctrine()->getManager();
                    $idUser = (int) $request->get('id');
                    var_dump($idUser);
                    $usersRepository = $this->getDoctrine()->getRepository(Users::class);
                    $user = $usersRepository->find($idUser);
                    $file = $request->files->get('bandeau');
                    var_dump($file);
                    $directory = $this->get('kernel')->getRootDir() . '/../web/uploads/'.$user->getSalt();
                    $bandeau_existant = $this->get('kernel')->getRootDir() . '/../web/uploads/'.$user->getSalt().'/bandeau.png';
    
                    if (file_exists($bandeau_existant)){
                        rename($bandeau_existant, $directory.'/old-bandeau.png');
                        rename($file, $bandeau_existant);
                    }else{
                        rename($file, $bandeau_existant);
                        $user->setCompteBandeau(1);
                        $em->persist($user);
                        $em->flush();
                    }   
                }
                //return new Response(['ok' => true]); //problème au niveau d'ici peut etre psq ne renvoie pas un json correct askip , 'file' => $file
                return new JsonResponse($file);
            }catch (Throwable $e){
                return new JsonResponse(['ok' => false, 'error' => $e->getMessage()]);
            }
        }

    Mon but est de renvoyer au success de mon ajax mon image qui vient d'être upload pour que je puisse ensuite l'insérer directement dans ma vue.

    Merci d'avance pour toute aide,

    Julien



    • Partager sur Facebook
    • Partager sur Twitter
      8 juin 2021 à 13:53:21

      Bonjour,

      Si tu es sous Symfony le try catch est inutile.

      Je ne vois pas où tu transmets l'id du user dans l'appel de ton ajax ?

      Ce que je ferai ...

      data: {
           id: id
      }

      Je ne pense pas que ce soit le $file qu'il faut renvoyer mais uniquement le chemin de ton fichier uploader et en faisant un json correct style :

      return new Response(json_encode['path' => $path_du_fichier]);

      Et ensuite tu mets dans le src de la balise <img> le path retourné dans success. Ou est la balise <img> d'ailleurs car pour afficher une image c'est quand même la norme.

      A+

      • Partager sur Facebook
      • Partager sur Twitter
        8 juin 2021 à 15:53:26

        Bonjour Monkey,

        Tout d'abord merci pour ton aide, j'ai réussi ce que je voulais faire !

        J'ai enlever le try catch; Pour l'id je pense qu'il passait dans le 

        data: new FormData(this)

        vu que j'arrive à le récupérer dans mon php...

        Pour la balise img elle était bien présente, j'ai omis de la mettre plus haut.

        Je mets ci-dessous mes fonctions :

            /**
             * @Route("/update_bandeau", name="update_bandeau", options={"expose"=true})
             */
            public function update_bandeau(Request $request)
            {
        
                if ($request->isXmlHttpRequest()) {
                    $em = $this->getDoctrine()->getManager();
                    $idUser = (int) $request->get('id');
                    $usersRepository = $this->getDoctrine()->getRepository(Users::class);
                    $user = $usersRepository->find($idUser);
                    $file = $request->files->get('bandeau');
                    $directory = $this->get('kernel')->getRootDir() . '/../web/uploads/'.$user->getSalt();
                    $bandeau_existant = $this->get('kernel')->getRootDir() . '/../web/uploads/'.$user->getSalt().'/bandeau.png';
                    $file_path = '/uploads/'.$user->getSalt().'/bandeau.png';
        
                    if (file_exists($bandeau_existant)){
                        rename($bandeau_existant, $directory.'/old-bandeau.png');
                        rename($file, $bandeau_existant);
                    }else{
                        rename($file, $bandeau_existant);
                        $user->setCompteBandeau(1);
                        $em->persist($user);
                        $em->flush();
                    } 
                    return new Response(json_encode(['path' => $file_path]));
                }else{
                    throw new Exception("Erreur");
                }
            }
        $(document).on('submit', '#update_bandeau', function(event){ 
            event.preventDefault();
            $.ajax({
                type: 'POST',
                async: false,  
                data: new FormData(this), 
                contentType: false,
                processData: false,
                cache: false,
                url: Routing.generate('update_bandeau'),
                success:function(result){
                    console.log(result);
                    var data = jQuery.parseJSON(result);
                    console.log(data['path']);
                    $('#bandeau_admin').attr('src', data['path']);
                },
                error:function(){
                    alert('Erreur');
                }
            });
        });
        <img id="bandeau_admin" src="https://sandbox.compublique.fr/uploads/'+result.user.salt+'/bandeau.png" style="display: block; margin: auto; max-width: 90%;">
        <br>
        <form id="update_bandeau" enctype="multipart/form-data">
        <input class="center-block btn-info" name="bandeau" type="file" style="margin-bottom:10px;" accept="image/*" required/>
        <input name="id" type="hidden" value="'+result.user.id+'">
        <button id="submit_bandeau" type="submit" name="submit" class="btn btn-success center-block">Importer un nouveau bandeau pour l\'utilisateur</button>
        </form>


        Maintenant le problème que j'ai c'est qu'en changeant la source je me retrouve à avoir une erreur 403 (forbidden access) du fait que ces images "appartiennent" à l'utilisateur (via le salt)... 

        Si jamais tu as une idée de comment je peux régler ça ou qqn d'autre (j'imagine que ça doit être dans les fichiers configs??)

        Merci encore,

        Julien



        • Partager sur Facebook
        • Partager sur Twitter
          8 juin 2021 à 16:02:48

          L'id est bien dans le this mais tu passes alors toutes les infos et cela peut amener problème de performance voire de sécurité. Détail j'en conviens.

          Pourquoi ajoutes-tu le salt ? car si les images ne doivent être vues que par l'utilisateur qui a uploadé, une relation entre image ou file et user ne conviendrait pas mieux ?

          Ou/et alors mettre les images dans un répertoire propre à chaque utilisateur ?

          A+

          -
          Edité par monkey3d 8 juin 2021 à 16:03:00

          • Partager sur Facebook
          • Partager sur Twitter
            8 juin 2021 à 16:28:47

            C'est ce qui se passe, en fait je dois réaliser la gestion du bandeau (image) des utilisateurs. Quand l'image est uploadé elle est donc mise dans le répertoire upload propre à l'utilisateur qui est identifié par son salt.

            Le fait est qu'une fois upload un nouveau bandeau l'image n'apparait pas car j'ai l'erreur suivante : Server error 403 forbidden You do not have permission to access this document.

            Et c'est la que je coince...

            En tant qu'admin il faudrait que l'accès me soit autoriser pour upload le nouveau bandeau et qu'il s'affiche ensuite. Et en réalité ça marche vu que lors de l'upload le nouveau bandeau est bien mis dans le dossier de l'utilisateur.

            Juste sur mon affichage de ma page le nouveau bandeau ne s'affiche pas à cause de l'erreur cité au-dessus...

            A+

            • Partager sur Facebook
            • Partager sur Twitter
              8 juin 2021 à 17:44:00

              ok. 

              Si tu es sous Linux, quels sont les droits, propriétaire et groupe des répertoires utilisateurs ?

              A+

              • Partager sur Facebook
              • Partager sur Twitter
                9 juin 2021 à 15:15:40

                Salut Monkey3d,

                Tu as raison c'est à cause des droits et du cache que mon image ne se rafraichit pas après upload.

                Je vais regarder comment faire pour modifier les droits en php + vider le cache dans ma fonction php.

                Si tu as des pistes d'aides je suis preneur ! :)

                A+

                Julien

                • Partager sur Facebook
                • Partager sur Twitter
                  9 juin 2021 à 15:21:48

                  Les répertoires où tu stockes les images doivent avoir pour propriétaire apache (voire groupe) puisque c'est lui qui écrit dedans.

                  Si tu es sous Linux, la commande est :

                  $ sudo chown -Rf apache:apache (attention moi c'est apache sous Fedora mais sous Debian c'est peut-être un autre nom).

                  Tu peux aussi faire un

                  $ sudo chmod -Rf 666 racine_répertoire

                  J'aime moins ... 

                  Le "racine_répertoire" doit être juste au dessus du salt de chaque utilisateur

                  A+

                  • Partager sur Facebook
                  • Partager sur Twitter
                    9 juin 2021 à 17:16:35

                    Nickel j'ai réussi à changer les droits de mon image qui s'upload !

                    Maintenant dernier problème...

                    Il faut que je trouve un moyen de clear mon cache soit à chaque fois que je vais sur /admin soit sinon dans ma function upload_bandeau

                    Parce qu'actuellement l'image s'upload bien etc mais elle ne s'affiche pas directement du fait que l'ancien bandeau est encore dans le cache...

                    J'ai regardé cette solution: https://stackoverflow.com/questions/1037249/how-to-clear-browser-cache-with-php#:~:text=You%20can%20delete%20the%20browser,%3Ai%3As")%20.

                    J'ai donc placé ces headers en dessous de mes use (sur Symfony) dans mon controller mais cela n'as pas marché :/

                    Si j'avais qqn connait une autre solution ou un autre moyen de vider mon cache au moment de l'upload je suis preneur !

                    A+

                    Julien

                    • Partager sur Facebook
                    • Partager sur Twitter
                      9 juin 2021 à 18:04:05

                      Il ne faut pas vider le cache car ta page si elle contient d'autres parties ne va plus fonctionner mais actualiser le tag img qui a eu le nouveau src.

                      Avec jquery tu peux utiliser load.

                      https://openclassrooms.com/fr/courses/1567926-un-site-web-dynamique-avec-jquery/1569757-la-methode-load

                      A+

                      • Partager sur Facebook
                      • Partager sur Twitter
                        10 juin 2021 à 11:30:20

                        Salut Monkey,

                        Merci encore une fois de ta réponse mais je suis tjr en galère...

                        Voici ma fonction:

                        $(document).on('submit', '#update_bandeau', function(event){ 
                            event.preventDefault();
                            $.ajax({
                                type: 'POST',
                                async: false,  
                                data: new FormData(this), 
                                contentType: false,
                                processData: false,
                                cache: false,
                                url: Routing.generate('update_bandeau'),
                                success:function(result){
                                    console.log(result);
                                    var data = jQuery.parseJSON(result);
                                    console.log(data['path']);
                                    $('#bandeau_admin').attr('src', data['path']);
                                    
                                },
                                error:function(){
                                    alert('Erreur');
                                }
                            });
                            $('#bandeau_admin').load();
                        });

                        Même en ayant rajouté le .load() rien ne se passe...

                        Je m'y prend surement mal, si tu as une idée de pourquoi ça ne marche pas stp

                        A+

                        • Partager sur Facebook
                        • Partager sur Twitter
                          10 juin 2021 à 11:31:55

                          A priori faut mettre le load juste après l'actualisation du src soit plutôt ligne 16.

                          A+

                          • Partager sur Facebook
                          • Partager sur Twitter
                            10 juin 2021 à 11:39:17

                            Ca n'as pas fonctionné :/

                            Je continue de chercher si tu as ou qqn a une autre idée n'hésitez pas !

                            A+

                            • Partager sur Facebook
                            • Partager sur Twitter
                              10 juin 2021 à 13:59:56

                              Tu peux vérifier que ton src est bon même s'il n'est pas actualisé ?

                              A+

                              • Partager sur Facebook
                              • Partager sur Twitter
                                10 juin 2021 à 15:37:48

                                Victoire !!! Ca à marché :)

                                Merci beaucoup pour ta précieuse aide !

                                Je poste ici ma fonction ajax finale pour ceux qui veulent et je passe le sujet en résolu

                                $(document).on('submit', '#update_bandeau', function(event){ 
                                    event.preventDefault();
                                    $.ajax({
                                        type: 'POST',
                                        async: false,  
                                        data: new FormData(this), 
                                        contentType: false,
                                        processData: false,
                                        cache: false,
                                        url: Routing.generate('update_bandeau'),
                                        success:function(result){
                                            var data = jQuery.parseJSON(result);
                                            $('#bandeau_admin').attr('src', data['path']+'?timestamp=" '+ new Date().getTime()+'');
                                        },
                                        error:function(){
                                            alert('Erreur');
                                        }
                                    });
                                });

                                Encore merci Monkey

                                A+

                                Julien

                                • Partager sur Facebook
                                • Partager sur Twitter

                                Ajax Upload image + affichage

                                × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                • Editeur
                                • Markdown