Simple upload en drag and drop avec HTML5 / Jquery / PHP

Il existe actuellement plusieurs plugins qui gèrent les uploads en drag and drop avec HTML5, et avec une pléthore d’options. Mais c’est bien là le problème. Encore un plugin lourd pour effectuer une action simple. Le but ici est de mettre en place un système permettant de télécharger une image sur un serveur, en glissant une image simplement dans une « dropbox » présente sur une page web ; rien de plus.

Posons les bases

Je commence juste par créer la dropbox de base :

<div id="dropfile">Drop an image from your computer</div>

Avec son petit code css :

#dropfile{
width: 300px;
height: 50px;
border: 3px dashed #BBBBBB;
line-height:50px;
text-align: center;
}

 

Jquery

Je commence par initialiser tous les évènements liés au drag et au drop, afin d’éviter la propagation des évènements.

 

$(document).on('dragenter', '#dropfile', function() {
            $(this).css('border', '3px dashed red');
            return false;
});

$(document).on('dragover', '#dropfile', function(e){
            e.preventDefault();
            e.stopPropagation();
            $(this).css('border', '3px dashed red');
            return false;
});

$(document).on('dragleave', '#dropfile', function(e) {
            e.preventDefault();
            e.stopPropagation();
            $(this).css('border', '3px dashed #BBBBBB');
            return false;
});

 

Un peu de CSS est rajouté afin d’avoir une petite animation suivant les différents évènements.

Maintenant je m’occupe de l’événement drop, qui va lancer toutes les actions à faire au moment où on va lâcher notre image dans la dropbox.

 

$(document).on('drop', '#dropfile', function(e) {
            if(e.originalEvent.dataTransfer){
                       if(e.originalEvent.dataTransfer.files.length) {
                                   // Stop the propagation of the event
                                   e.preventDefault();
                                   e.stopPropagation();
                                   $(this).css('border', '3px dashed green');
                                   // Main function to upload
                                   upload(e.originalEvent.dataTransfer.files);
                       }  
            }
            else {
                       $(this).css('border', '3px dashed #BBBBBB');
            }
            return false;
});

 

La fonction principale pour l’upload de mon image, commence par effectuer un contrôle sur le type de fichier, puis nous utilisons FileReader, un objet d’une API disponible avec HTML5 : File. Cet objet va permettre de lire directement le fichier depuis le navigateur.

La chose importante à comprendre avec la lecture de fichier depuis le navigateur, c’est que le traitement est asynchrone. C’est normal, le temps que la lecture de l’image se fasse, le script continu de tourner.

Je vais donc ordonner l’exécution d’une nouvelle fonction (handleReaderLoad), lorsque l’image sera chargée (reader.onload).

 

function upload(files) {
            var f = files[0] ;

            // Only process image files.
            if (!f.type.match('image/jpeg')) {
                       alert(‘The file must be a jpeg image’) ;
                       return false ;
            }
            var reader = new FileReader();
 
            // When the image is loaded,
            // run handleReaderLoad function
            reader.onload = handleReaderLoad;
 
            // Read in the image file as a data URL.
            reader.readAsDataURL(f);            
}

 

La fonction handleReaderLoad va s’occuper d’uploader l’image sur le serveur dès que l’image est chargée dans le navigateur.

Rien de bien compliqué ici, c’est juste une requête Ajax avec l’image encodée en Base64.

 

function handleReaderLoad(evt) {
            var pic = {};
            pic.file = evt.target.result.split(',')[1];

            var str = jQuery.param(pic);

            $.ajax({
                       type: 'POST',
                       url: ‘url_to_php_script.php’,
                       data: str,
                       success: function(data) {
                                   do_something(data) ;
                       }
            });
}

 

Coté PHP

Pour PHP, comme souvent sur ce blog, j’utilise CodeIgniter. Donc voici le contrôleur qui gère le décodage de l’image et qui l’enregistre dans un dossier.

 

public function add_picture() {
    $this->form_validation->set_rules('file', 'file', 'trim|xss_clean|required');

    if ($this->form_validation->run()) {
         $file = $this->input->post('file');
         $name = md5(rand().time()."DuSelPourRenforcerMonHash").'.jpg';

         // Encode it correctly
         $encodedData = str_replace(' ','+',$file);
         $decodedData = base64_decode($encodedData);

         // Finally, save the image
         file_put_contents('/chemin/vers/dossier/images/'.$name, $decodedData) ;
         return TRUE;
                                  
     }
     show_404();
}

 

Voilà avec ce simple code, il est maintenant possible d’envoyer rapidement une image en drag and drop de votre site vers votre serveur, pour une photo de profil par exemple 😉

Vus : 3052
Publié par Maxime CHAILLOU : 11