Partage
  • Partager sur Facebook
  • Partager sur Twitter

Vérifier dimensions d'une image côté client

Sujet résolu
    9 octobre 2012 à 8:29:10

    Bonjour, :)
    Je souhaite créer une fonction (javascript) qui retourne true ou false en fonction de si la taille d'une image choisie à l'aide de la balise <input type="file" /> est inférieur ou supérieur à 800x600px avant d'uploader l'image sur le serveur. NB: je tiens absolument à ce que la fonction retourne une valeur booleenne. ;)
    Je n'arrive pas à récupérer les propriétés width et height de mon image. SVP...quelqu'un peut-il m'aider? ça fait des jours que je suis coincée là dessus. :(

    <script type="text/javascript"> 
    function verifTaille(){ <code type="javascript"><code type="javascript">
    file = document.getElementById("myFile").files[0]; 
    window.URL = window.URL || window.webkitURL; 
    img = new Image(); 
    img.src = window.URL.createObjectURL(file); 
    if(img.width > 800 || img.height > 600){ 
    return false; 
    }else{ 
    return true; 
    } 
    } 
    
    function verifier(){ 
    if (verifTaille()){ 
    alert("votre image est trop grande, veuillez en choisir une autre"); 
    }else{ 
    uploaderFichier(); 
    } 
    } 
    </script>
    


    et dans body :

    <body> 
    ... 
    <input id="myFile" type="file" onchange="verifier()"> 
    ... 
    </body>
    
    • Partager sur Facebook
    • Partager sur Twitter
      9 octobre 2012 à 9:17:09

      window.URL = window.URL || window.webkitURL

      Ca te met la variable URL à true si au moins l'un des deux membres du test logique est à true car la partie de droite de ton affectation est un test logique.

      Donc tu risque pas d'avoir d'url dedans..

      Je t'invite à relire les bases de l'algorithmie et des tests logiques.
      • Partager sur Facebook
      • Partager sur Twitter
      Elmsroth  - Ingénieur informatique - Web & Logiciel
      Anonyme
        9 octobre 2012 à 9:33:52

        Bonjour,

        Après quelques tests j'ai pu trouver l'origine de ton problème.
        En effet il est est nécessaire de vérifier les dimensions à la fin du chargement de ton image.
        Or dans ton cas tu cherches à récupérer les informations de ton image tandis qu'elle n'a pas encore / est intégralement chargée, donc cela donne de fausses informations.

        La solution est comme expliquée précédemment, voici un exemple :

        /**
         * Vérifie que la taille de l'image respecte les dimensions demandées
         *
         * @param inputName ID de l'input de type file
         * @param maxWidth Largeur maximale
         * @param maxHeight Hauteur maximale
         * @return True si la taille est conforme ; sinon false
         */
        function verifTaille(inputName, maxWidth, maxHeight) {
            var file = document.getElementById(inputName).files[0]; 
            var fileUrl = (window.URL || window.webkitURL || window.MozURL || window.MsURL).createObjectURL(file);
            var img = new Image(); 
            
            img.onload = function() {
                // ...
            };
            
            img.src = fileUrl; 
            
            return (img.width <= maxWidth && img.height <= maxHeight);
        }
        


        Le soucis qui va alors se poser est qu'il va falloir arriver à mettre en pause l’exécution du reste de ton code pendant que celle-ci va se charger.

        En espérant t'avoir aidé au mieux.
        Cordialement.
        • Partager sur Facebook
        • Partager sur Twitter
          9 octobre 2012 à 10:06:35

          Elmsroth, tu dis n'importe quoi. Son code affecte simplement la valeur du premier élément testé, à moins qu'il soit à false/null/undefined, puis teste le second, etc.

          Je penche aussi sur un problème de chargement. Même si le chargement est quasi instantané, il vaut mieux attendre l'événement load.


          note. Je te conseille d'attribuer tes événements en DOM et pas en écrivant dans un attribut HTML.
          • Partager sur Facebook
          • Partager sur Twitter
            9 octobre 2012 à 14:00:38

            Moi je ne vois qu'un test logique à droit, si il veut un résultat dans sa variable il est en principe nécessaire au moins de transformer ça en ternaire non ?
            • Partager sur Facebook
            • Partager sur Twitter
            Elmsroth  - Ingénieur informatique - Web & Logiciel
              9 octobre 2012 à 14:59:37

              Non, pas forcément.

              Exemple :

              var a = null, b, c = false, d= 1;
              
              alert(a || b || c || d); // annonce 1
              


              Ici, il faut le lire "annonce a, ou à défaut b, ou à défaut c, ou à défaut d".

              Les conditions ternaires permettent de faire des opérations plus poussées. J'ai pas d'exemple à l'esprit, mais il y a des ternaires qu'on ne peut pas formuler de cette façon.
              • Partager sur Facebook
              • Partager sur Twitter
                9 octobre 2012 à 15:20:42

                Il ne faut pas oublier que JavaScript est un langage faiblement typé. Ceci permet d'avoir des opérateurs qui fonctionnent avec des types différent. L'opérateur || en est un.

                Fonctionnellement il évalue le membre de gauche en Booléen s'il vaut true alors il retourne la valeur du membre de gauche (et non pas sa valeur convertit en booléen) sinon il retourne la valeur du membre de droite.

                Cette propriété est très souvent utilisé pour affecter une valeur par défaut.
                Les ternaires sont plus souvent utilisées dans des conditions plus complexe ou quand le type est important a=(a||a===0)?a:""; (on n'affectera "" à a que s'il vaut null,"",undefined ou false)
                • Partager sur Facebook
                • Partager sur Twitter
                  9 octobre 2012 à 18:43:38

                  Merci à tous pour vos réponse. Comme vous l'avez surement remarqué je ne suis pas vraiment experte en la matière.

                  Je pense que la solution proposée par 0xFuture est ma meilleure piste pour l'instant.

                  Citation : 0xFuture

                  Le soucis qui va alors se poser est qu'il va falloir arriver à mettre en pause l’exécution du reste de ton code pendant que celle-ci va se charger.


                  En effet, j'ai réussi à mettre l'exécution du reste de mon code en "pause" jusqu'à ce que l'image se charge complètement. Pour ce faire j'ai donc inséré une fonction sleep() - que j'ai déniché sur un autre forum - à la ligne 19.

                  /**
                   * Vérifie que la taille de l'image respecte les dimensions demandées
                   *
                   * @param inputName ID de l'input de type file
                   * @param maxWidth Largeur maximale
                   * @param maxHeight Hauteur maximale
                   * @return True si la taille est conforme ; sinon false
                   */
                  function verifTaille(inputName, maxWidth, maxHeight) {
                      var file = document.getElementById(inputName).files[0]; 
                      var fileUrl = (window.URL || window.webkitURL || window.MozURL || window.MsURL).createObjectURL(file);
                      var img = new Image(); 
                      
                      img.onload = function() {
                          // ...
                      };
                      
                      img.src = fileUrl; 
                      sleep(1000); //met l'exécution du code en "pause" pendant 1 seconde (le temps que l'image se charge pour récupérer img.width et img.height).
                      return (img.width <= maxWidth && img.height <= maxHeight);
                  }
                  


                  Voici ma fonction sleep()
                  function sleep(milliSeconds){
                  	var resource;
                  	var response;
                  	if(typeof ActiveXObject == 'undefined'){
                  		resource = new XMLHttpRequest();
                  	}
                  	else{
                  		// IE
                  		resource = new ActiveXObject("Microsoft.XMLHTTP");
                  	}
                  
                  	try{
                  		resource.open('GET', 'sleep.php?milliSeconds=' + milliSeconds, false);
                  		resource.send(null);
                  		response = resource.responseText; // JavaScript waits for response
                  	}
                  	catch(e){
                  		alert(e);
                  	}
                  	
                  	return true;
                  }
                  


                  sleep.php
                  <?PHP
                  	$milliSeconds = intval($_REQUEST['milliSeconds']);
                  	if($milliSeconds > 60*1000){
                  		// limit server abuse
                  		$milliSeconds = 10;
                  	}
                  	
                  	usleep($milliSeconds * 1000); // note: usleep is in micro seconds not milli
                  	echo "done";
                  ?>
                  


                  ça fonctionne super bien sur Firefox :). j'arrive à récupérer les propriétés width et height de mon image. Mais le (nouveau) problème c'est que mon sleep() :D n'est pas compatible avec Google Chrome :(. ça me retourne toujours true quelle que soit la taille de l'image.
                  • Partager sur Facebook
                  • Partager sur Twitter
                    9 octobre 2012 à 19:25:09

                    Mon dieu non ! ça n'a aucun sens ce que tu fais. Pourquoi interroger le serveur pour attendre (déjà, il y a setTimeout qui est fait pour ça) quand il suffit d'exploiter l'événement load ? Et puis c'est quoi cette volonté farouche de faire absolument un return ?

                    <input id="myFile" type="file" />
                    


                    var input = document.getElementById("myFile");
                    
                    function verifTaille(){
                        file =input.files[0];
                        window.URL = window.URL || window.webkitURL;
                        img = new Image();
                        
                        img.onload = function(){ // à l'événement load, je lance la suite
                            if(img.width > 800 || img.height > 600){
                                pasGlop();
                            }else{
                                glop();
                            }
                        }
                        img.src = window.URL.createObjectURL(file);
                    }
                    
                    // je définis la suite ici pour aérer
                            
                    function glop(){
                           alert("ok c'est cool");
                    }
                    
                    function pasGlop(){
                           alert("votre image est trop grande");
                    }
                        
                    // l'événement ici pour faire propre
                    
                    input.onchange=verifTaille;
                    


                    C'est tout.

                    et si tu veux mettre en exergue le code à exécuter après le chargement, tu fais ce qu'on appelle un callback

                    var input = document.getElementById("myFile");
                    
                    function verifTaille(pasGlop, glop){ // j'ai deux arguments
                        file =input.files[0];
                        window.URL = window.URL || window.webkitURL;
                        img = new Image();
                        
                        img.onload = function(){ // à l'événement, j'exécute l'un des deux
                            if(img.width > 800 || img.height > 600){
                                pasGlop();
                            }else{
                                glop();
                            }
                        }
                        img.src = window.URL.createObjectURL(file);
                    }
                        
                    input.onchange=function(){
                       verifTaille( // je place mes fonctions à exécuter en argument
                          function(){alert("votre image est trop grande"),
                          function(){alert("ok c'est cool")}
                       );
                    };
                    


                    mais ça sert pas forcément à grand chose
                    • Partager sur Facebook
                    • Partager sur Twitter
                      9 octobre 2012 à 20:13:50

                      Citation : Geoffrey-Zéro

                      Mon dieu non ! ça n'a aucun sens ce que tu fais. Pourquoi interroger le serveur pour attendre (déjà, il y a setTimeout qui est fait pour ça) quand il suffit d'exploiter l'événement load ?


                      Désolée de t'avoir choqué :(
                      C'était le seul moyen que j'ai trouvé pour pour interrompre l'éxécution de mon code en attendant que l'image se charge complètement...Tout ça dans le but de pouvoir en récupérer les propriétés width et height. Tandis que si j'avais utilisé setTimeout, la récupération des dimensions de l'image n'aurait pas attendu le chargement de cette dernière et j'aurais obtenu un img.width(et img.height) égal à 0.

                      Citation : Geoffrey-Zéro

                      Et puis c'est quoi cette volonté farouche de faire absolument un return ?


                      Pour résumer la situation, je veux juste récupérer les valeurs de img.width et img.height sans avoir à recharger la page.

                      en d'autres termes

                      au lieu de:

                      function glop(){
                             alert("ok c'est cool");
                      }
                      
                      function pasGlop(){
                             alert("votre image est trop grande");
                      }
                      


                      je voudrais un truc qui ressemble à :

                      function glop(){
                             alert(imgWidth + "x" + imgHeight + "px. ok c'est cool");
                      }
                      
                      function pasGlop(){
                             alert(imgWidth + "x" + imgHeight + "px. votre image est trop grande");
                      }
                      
                      • Partager sur Facebook
                      • Partager sur Twitter
                        9 octobre 2012 à 22:42:31

                        En l'occurrence, l'image que tu as créé n'est pas directement accessible en dehors de verifTaille, donc tu ne peux pas utiliser ses propriétés dans glop et pasGlop comme ça. Mais qu'à cela ne tienne, tu peux les passer en argument quand tu les appelles dans verifTaille (genre glop(img.width, img.height); et dans la déclaration de la fonction glop tu prévois les arguments glop(imgWidth,imgHeight){/* le code */})

                        Ma réaction n'est pas tellement à ton encontre. Je suis atterré que quelqu'un ait jamais écrit cette fonction, et j'en veux un peu à 0xFuture d'avoir proposé de mettre le script "en pause" (j'avais pas relevé la première fois). Les événements sont là pour ne pas avoir à recourir à ce genre de technique imprécise et coûteuse. ça peut paraître un peu abstrait quand on débute mais il est important de savoir quand le code est exécuté et dans quel contexte. ça vient avec la pratique et en suivant le cours.
                        • Partager sur Facebook
                        • Partager sur Twitter
                          12 octobre 2012 à 9:19:25

                          Après plusieurs jours de recherches sur d'autres forums, j'en suis arrivée à la conclusion qu'il est apparemment impossible de faire ce que je cherche à réaliser. Je trouve ça quand même un peu absurde qu'on puisse afficher et pas récupérer les dimensions d'une image à partir de l'évènement onChange d'une balise "<input type="file" />" étant donné toutes les choses plus complexes qu'on peut faire avec javascript.
                          En tout cas, merci a tous d'avoir répondu.

                          (problème non résolu.)
                          • Partager sur Facebook
                          • Partager sur Twitter
                            12 octobre 2012 à 10:13:06

                            Soit tu ne lis pas, soit tu n'as pas les bases pour comprendre ce qu'on te dit, mais la solution a été donnée et ça marche très bien.

                            Donc va faire un tour sur le tuto officiel et comble tes lacunes plutôt que de demander des trucs à droite à gauche. C'est un conseil que je te donne.
                            • Partager sur Facebook
                            • Partager sur Twitter
                              12 octobre 2012 à 14:19:36

                              mille excuses, j'avais mal compris :euh: , aux temps pour moi. Merci pour le conseil, en effet j'ai encore beaucoup à apprendre. Sur ce, je mets le problème en "résolu". Encore merci.
                              • Partager sur Facebook
                              • Partager sur Twitter

                              Vérifier dimensions d'une image côté client

                              × 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