Cette première partie est un rapide tour d'horizon des différentes méthodes pour y parvenir.
1) Envoi d'un fichier avec un formulaire multipart/form-data
La méthode la plus simple est d'utiliser une balise <input name="img" type="file">
<form id="uploadForm" enctype="multipart/form-data" method="post" action="upload.php">
<input id="MAX_FILE_SIZE" type="hidden" name="MAX_FILE_SIZE" value="3145728">
<input name="img" type="file">
<input id="uploadButton" type="submit" name="Submit" value="Charger">
</form>
Les données sont envoyés au fichier upload.php sur le serveur. On utilise move_uploaded_file pour déplacer le fichier et le traiter comme on veut (redimensionnement, effets sur l'image, création d'une vignette). Simple mais fonctionnel.
Avantages :
- Très simple à mettre en oeuvre
- Fonctionne sur tous les navigateurs et systèmes
- Fonctionne sans Javascript
Inconvénients :
- L'utilisateur doit attendre que le chargement soit terminé sans avoir d'information sur son avancé
- Si un problème survient pendant le chargement il ne peut pas le savoir
2) Envoi d'un fichier avec jQuery et AjaxForm
Avec jQuery et le plug-in jQuery Form il est possible de résoudre les problèmes de la méthode précédente. Le code HTML est le même, mais on rajoute un soupçon de Javascript. Il faut commencer par charger les librairies 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>
Puis on ajoute le code Javascript suivant :
$("#uploadButton").on("click", function(){
$("#uploadForm").ajaxForm({
beforeSend: function(){
// avant l'envoi du fichier
},
uploadProgress: function(event, position, total, percent){
// pendant l'envoi du fichier
},
success: function(){
// après l'envoi du fichier en cas de succès
},
error: function(){
// après l'envoi du fichier en cas d'erreur
},
complete: function(xhr){
// l'envoi du fichier est terminé
// on peut afficher la réponse du serveur PHP
}
});
});
En cliquant sur le bouton "Charger", on appelle la fonction AjaxForm qui va envoyer le formulaire #uploadForm de façon asynchrone. Il sera envoyé au fichier PHP qui va renvoyer sa réponse à Javascript. Le tout sans recharger la page. Avec uploadProgress on peut afficher la progression du chargement.
Avantages :
- Simple à mettre en oeuvre
- Fonctionne sur une grande variété de navigateurs et systèmes
Inconvénients :
- Si la programmation asynchrone est simple à mettre en oeuvre depuis un fichier HTML, elle peut devenir plus difficile à débogguer sur des projets d'applications complexes.
- Nécessite jQuery
- Ajoute une [ignoble] iFrame
- L'affichage de la progression ne fonctionne pas avec Internet Explorer < 10.
Article complet
J'ai écrit un article plus en détail sur la façon d'envoyer un fichier en ligne avec jQuery
3) Envoi d'un fichier avec XMLHttpRequest
Dernière possibilité, l'HTML5. Pour l'utilisateur, cette méthode va produire un résultat similaire à ce que l'on a fait avec jQuery mais… sans utiliser jQuery.
Pour ça il faut utiliser l'objet XMLHttpRequest. On va créer une fonction qui va initialiser un objet XMLHttpRequest, vérifier le poids et le type du fichier avant de l'envoyer. C'est ici qu'HTML5 entre en jeux avec l'api File, puisqu'il est possible d'otebnir des informations sur des fichiers stockés localement (sur la machine du visiteur).
function UploadFile(file){
// crée une nouvelle requette XMLHttpRequest
var objReq = new XMLHttpRequest();
if(!objReq.upload){
// la fonction upload n'est pas disponible dans le navigateur.
// On ne peut pas envoyer de fichier avec XMLHttpRequest, il faut prévoir une alternative
}else if(file.size>document.getElementById("MAX_FILE_SIZE").value){
// vérifie le poids du fichier avant de l'envoyer
}else if(!(file.type=="image/jpeg" || file.type=="image/png" || file.type=="image/gif")){
// le fichier n'est pas du bon type
}else{
// tout est ok, on peut envoyer le fichier
// on commence par créer un objet formData dans lequel
// on va ajouter les données que l'on souhaite envoyer
var formData = new FormData();
formData.append("img", file);
// crée une fonction pour afficher la progression de la requête
objReq.upload.onprogress = function(evt){
}
// onreadystatechange est appelé à chaque changement d'état de la requête
objReq.onreadystatechange=function(){
}
// ouvre une requete post, avec l'adresse du formulaire
objReq.open("POST", document.getElementById("uploadForm").action, true);
// on envoie l'objet formData
objReq.send(formData);
}
}
Comme pour chaque méthode, on peut accéder au fichier envoyé avec la variable $_FILES['img'] pour le manipuler ensuite à notre guise. On accédera aux autres type de variable que l'on a intégré à formData avec $_POST.
Avantages :
- Ne nécessite aucune librairie supplémentaire
- Ne nécessite pas la création d'une iFrame
- Moderne
Inconvénient :
- XMLHttpRequest nécessite un navigateur moderne.
Article complet
J'ai écrit un article plus en détail sur la façon d'envoyer un fichier en ligne avec HTML 5 et XMLHttpRequest