Pour commencer nous allons charger les deux libraires qui nous intéressent :
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="http://malsup.github.io/jquery.form.js"></script>
HTML
<form id="uploadForm" action="upload.php" method="POST" enctype="multipart/form-data">
<p><label for="img">Image : </label><input id="uploadImg" name="img" type="file" accept=".jpg,.png,.gif,image/png,image/jpg,image/gif"></p>
<p><label> </label><input type="submit" name="Submit" value="Charger le fichier"></p>
</form>
<div id="uploadProgress">
<h1>Chargement...</h1>
<div id="uploadProgressBar" class="progressBar"><span style="width: 0%"></span></div>
<p id="uploadProgressPercent"></p>
</div><!--uploadProgress-->
<div id="uploadResult">
<h1>Résultat</h1>
<div></div>
</div><!--uploadResult-->
Pour cet exemple on utilise la balise de formulaire suivante :
<form id="uploadForm" action="upload.php" method="POST" enctype="multipart/form-data">
- action contient l'adresse du fichier PHP qui va traiter le fichier.
- method est la méthode d'envoi du formulaire vers le serveur (GET ou POST). On choisit POST car GET est limité en taille.
- enctype précise la façon dont les données doivent être encodé lorsqu'elles sont envoyées vers le serveur. Pour envoyer des fichiers on utilise enctype="multipart/form-data". Plus d'info sur le site du W3C.
jQuery Form n'a pas besoin de enctype="multipart/form-data" pour fonctionner, mais il faut le laisser dans le cas où jQuery n'aurait pas été correctement chargé ou initialisé et que vous deviez envoyer le fichier à la façon moyenâgeuse.
Pour obtenir le fichier à charger on utilise un champ <input type="file" name="img" />. En PHP on accédera au fichier avec la variable $_FILES.
Le bloc #uploadProgress est affiché pendant le chargement. Il contient un span qui va servir de barre de progression et un paragraphe dans lequel on va noter le pourcentage de chargement.
Le bloc #uploadResult est affiché une fois le chargement terminé. Il contiendra la réponse du serveur. Soit l'affichage d'une image soit l'affichage d'une erreur.
Javascript
$(document).ready(function(){
$("#uploadForm").ajaxForm({
// attache l'événement au formulaire.
beforeSend: function(){
// avant l'envoi du fichier
$("#uploadProgressPercent").html("Chargement en cours");
$("#uploadResult").fadeOut(400, function(){
$("#uploadProgress").fadeIn();
});
},
uploadProgress: function(event, position, total, percent){
// pendant l'envoi du fichier
$("#uploadProgressBar > span").width(percent+'%');
$("#uploadProgressPercent").html(percent+'%');
},
success: function(){
// après l'envoi du fichier
$("#uploadProgressBar > span").width('100%');
$("#uploadProgressPercent").html("Chargement terminé");
},
complete: function(xhr){
// l'envoi du fichier est terminé
$("#uploadResult > div").html(xhr.responseText);
$("#uploadProgress").fadeOut(400, function(){
$("#uploadResult").fadeIn();
});
}
});
});
On attache un événement ajaxForm au formulaire qui prendra la main lorsque le formulaire sera envoyé. Soit en cliquant sur le bouton submit soit en appuyant sur la touche Enter.
AjaxForm propose une vingtaine d'options que vous pouvez utiliser en plus des options $.ajax de jQuery :
- beforeSend est appelé juste avant l'envoi du fichier. Dans cet exemple on prépare l'affichage en masquant le bloc #uploadResult et en affichant #uploadProgress
- uploadProgress est appelé pendant l'envoi du fichier. C'est ici que l'on peut indiquer à l'utilisateur l'avancement du chargement.
- success est appelé juste après l'envoi du fichier, mais avant la réponse du serveur..
- complete est appelé quand le serveur a terminé son traitement. Il reçoit une réponse de type XHR c'est-à-dire XMLHttpRequest.
Un objet XHR contient deux options :
- responseText pour du texte
- responseXML pour des données XML
Dans cet exemple nous utiliserons responseText puisque le script PHP va retourner du texte.
PHP
<?php
$fUpload = 'upload/'; // dossier de destination
$fName = 'test'; // nom du fichier de destination
$fPost = $_FILES['img']; // fichier envoyé
// liste des format de fichier accepté
$lst = array('image/gif'=>'gif', 'image/jpeg'=>'jpg', 'image/pjpeg'=>'jpg', 'image/png'=>'png');
$fType = $lst[$fPost['type']]; // type du fichier qui nous intéresse
$fPath = $fUpload.$fName.'.'.$fType; // chemin complet après déplacement
if(empty($fType)){
// fichier inconnu
echo 'Fichier de type inconnu';
}else if(move_uploaded_file($fPost['tmp_name'], $fPath)){
// le fichier a été correctement déplacé
echo '<p>Image chargée : <b>'.$fName.'.'.$fType.'</b><br />
MIME : <b>'.$fPost['type'].'</b> <br />
Poids : <b>'.round(filesize($fPath) / 1024, 2).' Ko</b></p>
<p><img src="'.$fPath.'" height="200px" alt="'.$fName.'" /></p>';
}else{
// le fichier n'a pas été déplacé
echo 'erreur';
}
?>
Le script est très simple, on vérifie le type de fichier envoyé et on le déplace avec move_uploaded_file.
Une fois le déplacement terminé on affiche le nouveau nom de l'image, son type MIME, son poids et l'image.
Le script PHP affiche sa réponse sous forme de texte (avec echo). Ca nous permet de la traiter avec xhr.responseText en Javascript.
Pour utiliser xhr.responseXML, le script PHP devrait afficher un objet XML :
echo = '<?xml version="1.0" encoding="UTF-8"?>
<data>
<image>'.$fPath.'</image>
<mime>'.$fPost['type'].'</mime>
<poids>'.round(filesize($fPath) / 1024, 2).'</poids>
</data>';
Exemple concret
Voir cet exemple en fonctionnement.