mercredi 13 mai 2015

Upload de fichiers par formulaires avec php

05:03


L'utilisation des formulaires n'est pas des plus compliquées, et vous en avez certainement déjà utilisé pour créer votre site web, ne serait-ce que pour la page d'inscription et de connexion.
Mais dès que l'on souhaite aller plus loin, et proposer aux visiteurs de personnaliser leur avatar ou d'envoyer une image, cela devient plus difficile. Or, PHP propose des fonctions permettant justement de créer ce genre de script.

Upload c'est quoi  ?

Internet est un réseau mondial, regroupant des millions d'individus répartis sur le globe. Toutes ces personnes s'échangent des messages, partagent des fichiers, jouent ou cherchent des informations. Nous échangeons donc des données directement avec d'autres personnes ou avec des ordinateurs installés dans des locaux.
Tous ces transferts de données d'un ordinateur à l'autre se font par le biais de connexions, qu'elles soient filaires ou non-filaires (comme le célèbre WiFi). Une connexion est donc un lien entre deux ordinateurs.
L'ordinateur (ainsi que le logiciel) qui crée la connexion s'appelle le client, alors que celui qui « reçoit » la demande s'appelle le serveur.
 Pour chacun des ordinateurs, les données reçues constituent le download (téléchargement), alors que les données envoyées constituent l'upload (téléversement). Si vous avez bien compris, vous devriez alors voir que tout ce qui est de l'upload pour le client, est du download pour le serveur, et réciproquement.

Consulter un site web revient généralement à télécharger (download) les pages, images et autres fichiers qui forment la page que l'on souhaite. C'est le navigateur qui s'occupe de gérer toutes les connexions nécessaires, qui envoie les demandes de fichiers, reçoit les fichiers et affiche la page.
Mais depuis de nombreuses années, les sites s'ouvrent aux visiteurs de manière à leur permettre de participer à la vie du site. On trouve désormais bon nombre de forums, des galeries, et de nombreuses autres applications en ligne. Pour permettre aux visiteurs d'envoyer des données, la page contient un formulaire.
Donc, dans un premier temps, le visiteur sélectionne le fichier. Ensuite, après avoir rempli le reste du formulaire, il clique sur le bouton pour l'envoyer.
À ce moment-là, le navigateur du client demande au serveur la page « cible » (spécifiée grâce à l'attribut action du formulaire) en lui envoyant une requête HTTP. Dans cette requête, le navigateur fournit diverses informations (page demandée, nom et version du navigateur, cookies qu'il possède pour ce site, etc.) dont les données du formulaire.
Le serveur (Apache par exemple) analyse la requête et passe le relais à PHP. Juste avant de lancer l'exécution de la page demandée, PHP s'occupe des données envoyées par le formulaire :
  • les champs textuels (text, checkbox, select, textarea, ...) sont copiés dans le tableau superglobal $_POST ;
  • les informations concernant les champs de type file sont enregistrées dans le tableau superglobal $_FILES ;
  • les fichiers sont temporairement placés dans le dossier temporaire du serveur.

 Une fois que tout est prêt, PHP commence à exécuter le script de la page demandée. C'est donc le script PHP qui va pouvoir gérer le fichier. Il ne faudra pas oublier que le fichier est dans un dossier temporaire, et donc que si l'on souhaite le garder, il faudra le placer ailleurs (dans un dossier du site par exemple). Si au contraire on décide de ne pas garder le fichier (par exemple si on remarque qu'il est trop grand, que ce n'est pas une image, …) il suffit de ne pas le déplacer ; il sera effacé automatiquement lorsque le script aura fini d'être exécuté.
Nous allons voir plus en détail comment mettre en place le script.

Créer le formulaire

Bien, nous voici donc à la première étape : la création d'un formulaire. Le visiteur qui veut uploader un fichier doit passer par un formulaire.
Eh bien non, cela serait terriblement dangereux. En effet, s'il suffisait au script PHP d'avoir l'adresse du fichier pour pouvoir le prendre sur le disque dur du visiteur, un webmaster mal intentionné pourrait prendre tous les fichiers qu'il veut, et donc même ceux qui contiennent vos informations confidentielles ! C'est pourquoi on utilise un type de champ particulier où seul le visiteur pourra choisir le fichier que le navigateur va envoyer au serveur.
Il faut utiliser la balise XHTML <input /> que vous connaissez déjà sous trois formes :
Nous allons utiliser une autre forme de cette balise, qui permet au visiteur de sélectionner un fichier dans une liste. Elle est fortement semblable aux trois formes précédentes, mais son type est « file » et elle ne peut pas avoir de valeur par défaut :
Elle permet, comme vous le voyez, de sélectionner un fichier à envoyer. Vous pouvez en mettre autant que vous le souhaitez dans votre formulaire, mais n'oubliez pas de leur donner des noms différents.

L'entête du formulaire

Pour que le navigateur sache qu'il doit envoyer un fichier, on l'indique dans l'en-tête du formulaire. C'est très simple, mais il faudra bien y penser pour que votre formulaire fonctionne correctement.
Vous connaissez déjà la balise <form>, il ne devrait donc pas vous être difficile d'y ajouter une propriété. Il s'agit de la propriété enctype, qui indique le type d'encodage des données. Elle prendra la valeur « multipart/form-data », qui spécifie que le formulaire envoie des données binaires (fichier) et du texte (champs de formulaire). Ce qui nous donne ceci :
Profitons-en pour nous intéresser aux deux autres propriétés du formulaire.
  • method : c'est la façon dont les informations seront envoyées, soit par l'URL si la méthode est « GET », soit dans la requête HTTP si la méthode est « POST ». Dans le cas de l'envoi d'un fichier, cette propriété doit être placée à « POST », car le fichier ne peut pas être passé par l'URL ( ^^ ) . Il existe d'autres valeurs possibles, mais qui ne nous intéressent pas ici.
  • action : c'est la page qui sera appelée lors de l'envoi du formulaire. C'est-à-dire, par exemple, le script PHP qui va traiter la réception du fichier. Vous pouvez placer le script sur la même page que le formulaire, comme vous avez appris à le faire dans le cours PHP (que vous devez aussi avoir lu pour poursuivre ce tutoriel).

Restrictions

Un webmaster sain d'esprit ne laissera pas n'importe qui uploader n'importe quoi ( ^^ ) . C'est pourquoi il est nécessaire d'apprendre à restreindre l'envoi. Nous verrons par la suite que c'est en PHP que se fera la plus grosse partie de la vérification, mais il est déjà possible, en XHTML, de fixer une limite de taille sur l'envoi.
C'est en fait juste une variable que l'on communique au navigateur dans le formulaire. Comme le visiteur n'a pas besoin de voir ce champ, on lui attribue le type hidden.
Cette restriction se fait en octets. Normalement, depuis quelques années, 1 Go = 1 000 Mo = 1 000 000 Ko = 10^9 octets, mais cette norme n'est pas suivie par tout le monde.

Finalisations / Exemples

Nous avons maintenant vu tout ce qui est nécessaire pour réaliser un formulaire d'upload. Bien sûr, vous pouvez ajouter autant de champs que vous le souhaitez. Pour ma part, je vais par exemple ajouter un champ de type texte pour indiquer une brève description. J'ai aussi décidé de permettre au visiteur d'envoyer deux fichiers avec le formulaire. Au final, mon code XHTML ressemble à ceci :
La réalisation du formulaire est à présent terminée. Nous allons maintenant passer à la réception du fichier par le script PHP.

Récupérer le fichier

Poursuivons notre petite histoire. Le formulaire est en place ; le visiteur le remplit puis le valide. Comme je vous l'ai expliqué, les fichiers sont alors uploadés et placés dans un répertoire temporaire. L'avantage, c'est que seul le script PHP pourra accéder à ce dossier.
Nous allons donc contrôler le fichier puis le déplacer vers un dossier du site. On peut contrôler plusieurs choses : la taille, le type, le nom, les dimensions (si c'est une image), …
Le tableau $_FILES contient certaines informations sur les fichiers. Pour chaque champ de type file, on peut obtenir les informations le concernant dans le tableau $_FILES[attribut_name]. On retrouve actuellement les informations suivantes :

Contrôle sur le fichier

Une première vérification consiste à savoir si le fichier a bien été uploadé. Pour ce faire, nous allons utiliser le code d'erreur du fichier. Ensuite nous pourrons effectuer les autres tests.
On peut même préciser de quel type d'erreur il s'agit en comparant le code d'erreur à plusieurs constantes :
UPLOAD_ERR_NO_FILE : fichier manquant.
UPLOAD_ERR_INI_SIZE : fichier dépassant la taille maximale autorisée par PHP.
UPLOAD_ERR_FORM_SIZE : fichier dépassant la taille maximale autorisée par le formulaire.
UPLOAD_ERR_PARTIAL : fichier transféré partiellement.
Commençons par la taille maximale. Pas difficile, c'est une simple comparaison.
Pour le type, nous n'allons pas utiliser le type du tableau mais l'extension du fichier, ce qui sera plus simple. Rassurez-vous, cela revient exactement au même, car le type est pris en fonction de l'extension. Ce qui signifie aussi, malheureusement, qu'on ne peut pas être sûr de la nature du fichier.
Le moyen le plus efficace et le plus polyvalent est de placer les extensions autorisées dans un tableau puis de vérifier que l'extension du fichier est bien dans ce tableau. On pourrait aussi, si on souhaitait autoriser tous les types de fichier mis à part quelques uns, lister les extensions non autorisées et vérifier ensuite que l'extension du fichier uploadé ne s'y trouve pas. Pour cette dernière méthode, il suffit alors d'ajouter une négation à la condition grâce à « ! ».
Pour contrôler les dimensions d'une image, il suffit d'utiliser une fonction PHP, getimagesize(), qui retourne un tableau. Nous devons bien évidemment spécifier l'adresse du fichier, qui pour l'instant se trouve dans le dossier temporaire. La fonction retourne alors un tableau dont l'index 0 donne la largeur et l'index 1 la hauteur de l'image. C'est ici encore une simple condition.
En utilisant conjointement ces deux ou trois tests, on peut s'assurer que le fichier est correct et que nous pouvons donc le déplacer dans un dossier du site sans danger. Je ne vous ai pas donné le code final, mais vous devriez être capables de le réaliser facilement avec les lignes de code que je vous ai données. Si vous n'y arrivez pas, c'est que vous devriez sans doute relire le cours, car vous n'avez pas compris le fonctionnement de PHP.

Déplacer le fichier

Pour déplacer le fichier, nous avons besoin de deux informations : l'emplacement de départ, que nous connaissons déjà grâce à la variable superglobale $_FILES, et l'emplacement de destination, que nous devons fixer nous-mêmes. Ici, plusieurs possibilités s'offrent à nous.
Il est toujours important de bien choisir de quelle façon on va nommer les fichiers. Il faut se rappeler deux règles fondamentales : deux fichiers ne peuvent pas avoir le même nom dans le même dossier, et il faut faire attention à l'extension. Ce qui veut dire que l'on ne va presque jamais garder le nom de départ du fichier, car deux visiteurs différents pourraient avoir un fichier du même nom. Pour l'extension, nous verrons par la suite comment contourner le problème. Voici d'abord quelques exemples de noms :
  • un avatar : on peut lui donner le numéro unique (id) du membre (1, 2, 343, ...) ;
  • une image perso : on peut créer un dossier par membre (s'il peut uploader plusieurs fichiers) et garder le nom de départ ;
  • un tracker torrent : on peut lui attribuer un numéro unique (son id dans une BDD par exemple).
Il existe de nombreux autres choix possibles : attribuer un nom alphanumérique généré au hasard, la date actuelle, etc.
Quelques fonctions utiles :
Créer un dossier : boolmkdir string$pathname [, int$mode [, bool$recursive [, resource$context ]]])
Créer un identifiant alphanumérique unique : stringuniqid ([ string$prefix [, bool$more_entropy ]] ).
Pour l'extension, on a plusieurs possibilités. On peut garder celle de départ, s’il s’agit par exemple d'une image ou d'un document PDF. En revanche, si l'extension de départ est php ou html, mieux vaut changer l'extension pour éviter que le visiteur puisse placer ses propres scripts sur le site.
Il y a plusieurs façons de procéder : on peut se contenter d'ajouter une extension après celle déjà existante (par exemple page2.php deviendrait page2.php.file) ; on peut remplacer l'extension par une autre (page2.php deviendrait page2.file) ; ou on peut finalement retirer l'extension (page2.php deviendrait page2). Évidemment, lorsqu'un visiteur voudra télécharger le fichier, il faudra remettre l'extension correcte, mais nous verrons comment faire cela plus tard.
Une fois le nom du fichier choisi, il faut déplacer le fichier du répertoire temporaire vers le dossier de destination. Il existe pour cela une fonction très simple qui fonctionne presque exactement comme la fonction copy() ; il s'agit de la fonction move_uploaded_file(). La principale différence avec copy, c'est qu'elle vérifie également que le fichier que l'on souhaite déplacer provient bien d'un formulaire PHP. Voici un exemple d'utilisation :
La fonction renvoie vrai ou faux, selon que le fichier a bien été déplacé ou non. On peut donc s'assurer que le transfert a bien eu lieu, ce qui constitue la dernière étape dans l'upload du fichier.

0 commentaires:

Enregistrer un commentaire

 

© 2015 Galsen Coder's, by JokerSoft . Tous Droits Résèrvés.

Back To Top