Cette fiche aborde les possibilités offertes par PHP pour manipuler les fichiers. On verra entre autres comment en créer de différents types, comment les manipuler (avec PHP ou javascript), comment les télécharger, ou les enregistrer sur le serveur.
Points d'accés et navigation dans les répertoires
Répertoire exemple pour les informations sur les chemins
Un chemin en langage informatique correspond aux informations successives que l'on doit fournir pour atteindre le fichier ou le dossier recherché.
Les points d'entrée
Quel que soit le type de chemin choisi, il existe deux points d'entrée :
A partir du dossier où se situe le point d'entrée du script.
Utilisé par les développeurs pour construire leurs scripts, inclure des images, inclures d'autres fichiers etc.
Le chemin du point d'entrée à partir de la racine du serveur est donné par l'instruction
Lorsque l'on veut accéder à un site on appelle souvent un fichier index.php (mais on peut l'appeler autrement) qui se situe à la racine du site.
"http://monwebfacile.free.fr" sans préciser le fichier index qui est automatiquement chargé s'il existe, ou bien "http://monwebfacile.free.fr/Monfichier.php." en précisant le fichier à charger.
Toutes références de chemin à l'intérieur de ces fichiers se feront par rapport à la racine du site
Exemple 2 :
On peut aussi choisir un autre point d'entrée dans le site.
Les chemins relatifs se basent toujours sur le dossier où se situe le point d'entrée du programme., il est donc important de connaitre ce point d'accés.
Les chemins relatifs permettent de se rendre d'une ressource à l'autre en se promenant dans l'ensemble des répertoires pouvant contenir d'autres répertoires et/ou fichiers. Des règles élémentaires indiquent la marche à suivre pour aller d'une point à un autre dans l'arborescence du site web hébergé.
Descendre dans les répertoires
Soit une page web à la racine du site. On veut y ajouter sous forme d'include le fichier "Commun_Body_Tutos.txt".
<?php include "Tutoriaux/Includes/Commun_Body_Tutos.txt"; ?> => à partir de la racine pour atteindre le fichier on doit d'abord passer par le répertoire Tutoriaux puis par le répertoire "Includes" qui est lui-même un répertoire de "Tutoriaux" pour pouvoir accéder au fichier "Commun_Body_Tutos.txt".
Si la page web avait été dans le répertoire "Tutoriaux" on aurait du faire <?php include "Includes/Commun_Body_Tutos.txt"; ?>. Dans ce cas on n'avait plus à passer par le répertoire "Tutoriaux".
Qu'il y ait un ou plusieurs répertoires à descendre, le principe est toujours le même : descendre plusieurs répertoires équivaut à descendre plusieurs fois un répertoire.
Remonter dans les répertoires
Si la page web est à la racine du site on ne pourra pas remonter plus avant.
Si la page web est par exemple été dans le répertoire "Tutoriaux" et que l'on veuille aller chercher une ressource.
Qu'il y ait un ou plusieurs répertoires à remonter, le principe est toujours le même : remonter plusieurs répertoires équivaut à remonter plusieurs fois un répertoire.
__DIR__ => Le répertoire du fichier.
Pour éviter certains problèmes posés par la solution à base de dirname, PHP 5.3 introduit cette nouvelle constante magique.
Celle-ci vaut exactement la même chose que dirname(__FILE__), mais évite les deux problèmes soulevés par la solution à base de dirname, à savoir :
La syntaxe est trés courte, donc plus rapide à saisir, et ainsi diminue le risque de fautes de frappe lorsque la commande est souvent utilisée,
La constante est calculée à la compilation du code, entrainant un gain au niveau des performances.
Instructions de base pour la manipulation des fichiers et des chaines
fopen()
Création d'une ressource nommée, spécifiée par le paramètre $filename, sous la forme d'un flux.
Syntaxes
fopen(string $filename,string $mode)
Paramètre $filename
Nom du fichier avec son arborescence.
Paramètre string $mode
Valeurs
Commentaires
'r'
Ouvre en lecture seule, et place le pointeur de fichier au début du fichier.
'r+'
Ouvre en lecture et écriture, et place le pointeur de fichier au début du fichier.
'w'
Ouvre en écriture seule ; place le pointeur de fichier au début du fichier et réduit la taille du fichier à 0. Si le fichier n'existe pas, on tente de le créer.
'w+'
Ouvre en lecture et écriture ; place le pointeur de fichier au début du fichier et réduit la taille du fichier à 0. Si le fichier n'existe pas, on tente de le créer.
'a'
Ouvre en écriture seule ; place le pointeur de fichier à la fin du fichier. Si le fichier n'existe pas, on tente de le créer. Dans ce mode, la fonction fseek() n'affecte que la position de lecture, les écritures surviennent toujours.
'a+'
Ouvre en lecture et écriture ; place le pointeur de fichier à la fin du fichier. Si le fichier n'existe pas, on tente de le créer. Dans ce mode, la fonction fseek() n'affecte que la position de lecture, les écritures surviennent toujours.
'x'
Crée et ouvre le fichier en écriture seulement ; place le pointeur de fichier au début du fichier. Si le fichier existe déjà, fopen() va échouer, en retournant FALSE et en générant une erreur de niveau E_WARNING. Si le fichier n'existe pas, fopen() tente de le créer. Ce mode est l'équivalent des options O_EXCL|O_CREAT pour l'appel système open(2) sous-jacent.
'x+'
Crée et ouvre le fichier pour lecture et écriture; le comportement est le même que pour 'x'.
'c'
Ouvre le fichier pour écriture seulement. Si le fichier n'existe pas, il sera crée, s'il existe, il n'est pas tronqué (contrairement à 'w') et l'appel à la fonction n'échoue pas (comme dans le cas de 'x'). Le pointeur du fichier est positionné au début. Ce mode peut être utile pour obtenir un verrou (voyez flock()) avant de tenter de modifier le fichier, utiliser 'w' pourrait tronquer le fichier avant d'obtenir le verrou (vous pouvez toujours tronquer grâce à ftruncate()).
'c+'
Ouvre le fichier pour lecture et écriture, le comportement est le même que pour le mode 'c'.
'rb'
Ouvre le fichier en mode binaire.
Retour
Retourne une ressource représentant le pointeur de fichier, ou FALSE si une erreur survient.
fputs()
Ecrit en mode binaire une chaine de caractères dans le fichier référencé par la ressource retournée par fopen().
Syntaxe
fputs(ressource fichier, chaine de caractères, optionnel : longueur de la chaine)
Paramètres
Paramètre 1 : Pointeur de système de fichiers de type resource habituellement créé par la fonction fopen().
Paramètre 2 : La chaîne à écrire.
Paramètre optionnel : Si la longueur de la chaine est fournie, l'écriture s'arrêtera après le nombre d'octets défini, ou à la fin de la chaîne (le premier des deux).
fread()
Lecture d'un fichier en mode binaire
Syntaxes
string fread ( ressource fichier , int $length )
Paramètre 1 : Pointeur de système de fichiers de type resource habituellement créé par la fonction fopen().
Paramètre 2 : Taille length d'octets à lire. Une fois les données lues le pointeur de fichier est positionné à sa valeur initiale + $length.
Retour
Retourne la chaîne lue, ou FALSE si une erreur survient.
fgets()
Récupère la ligne courante sur laquelle se trouve le pointeur du fichier
unpack()
Déconditionne des données depuis une chaîne binaire.
Retour
Retourne un tableau associatif contenant les éléments déconditionnés d'une chaîne binaire.
fclose()
ferme le ficher
Syntaxes
fclose(ressource fichier )
explode()
Coupe une chaîne en segments. explode() retourne un tableau de chaînes, chacune d'elle étant une sous-chaîne du paramètre string extraite en utilisant le séparateur delimiter.
$infoSize[2] : L'index 2 est une constante parmi IMAGETYPE_XXX constants, indiquant le type de l'image.
$infoSize[3] : L'index 3 contient la chaîne à placer dans les balises IMG : height="xxx" width="yyy".
$infoSize["channels"] : en principe 3 pour des images RGB et 4 pour des images CMYK.
$infoSize["bits"] : nombre d'octets pour chaque couleur.
Plus d'autres informations de type IPTC (International Press Telecommunication Council) avec le paramètre optionnel imageinfo.
On utilisera iptcparse($imageinfo) pour analyser le bloc binaire IPTC et rechercher les balises simples. Cette partie est explicitée dans cette fiche au chapitre 'Lecture des tags de fichiers images'
Exemple
Dates des fichiers
Les fonctions suivantes permettent respectivement de déterminer la date d'accés, la date de modification (attributs,droits) etc ..
La valeur renvoyée correspond au nombre de secondes écoulées depuis le 1er janvier 1970 (c'est le format epoch UNIX). Il sera donc nécessaire d'utiliser la fonction date pour remettre en forme de cette valeur.
fileatime()
int fileatime ( string $filename )
Donne la date à laquelle le fichier a été accédé pour la dernière fois. Retourne FALSE si une erreur survient. Attention cette information n'est pratiquement jamais mise à jour par les systèmes.
filemtime()
int filemtime ( string $filename )
Donne la date à laquelle le fichier a été modifié pour la dernière fois. Retourne FALSE si une erreur survient.
filectime()
int filectime ( string $filename )
Renvoie la date à laquelle l'inode (1) a été accédé pour la dernière fois. Retourne FALSE si une erreur survient.
Formatage du résultat avec l'objet date
Note1 Un nœud d'index ou inode (contraction de l'anglais index et node) est une structure de données contenant des informations à propos d'un fichier stocké dans certains systèmes de fichiers (notamment de type Linux/Unix). À chaque fichier correspond un numéro d'inode (i-number) dans le système de fichiers dans lequel il réside, unique au périphérique sur lequel il est situé. Les inodes peuvent, selon le système de fichiers, contenir aussi des informations concernant le fichier, tel que son créateur (ou propriétaire), son type d'accès (par exemple sous Unix : lecture, écriture et exécution), etc (Source wikipedia).
Lecture de répertoires
Créer ou lire des fichiers texte pur, xml, json
Généralités
Structures
Fichiers texte pur
Fichiers xml
json
Créer ou lire un fichier PDF
Nous allons voir dans cette partie comment générer automatiquement un fichier PDF : son contenu, mais aussi les entêtes et pieds de page, ainsi que la possibilité d'appliquer un filigramme.
La librairie FPDF
Prérequis
Nous allons utiliser comme base la classe FPDF qui est une classe PHP permettant de générer des documents PDF en pur PHP, c'est-à-dire sans utiliser la librairie PDFlib. Cette librairie est libre de droit ce qui signifie que vous êtes libre de l'utiliser et de la modifier comme vous bon vous semble. Par exemple en ajoutant des classes pour répondre à vos besoins spécifiques : la classe de base est FPDF et si l'on veut ajouter un script, il suffit de créer une classe qui en hérite.
Principales fonctionnalités de FPDF
Choix des unités, du format des pages et des marges,
Gestion des en-têtes et pieds de page,
Saut de page automatique,
Saut de ligne automatique et justification,
Images (JPEG et PNG),
Couleurs,
Liens,
Support des polices TrueType et Type1,
FPDF ne nécessite aucune extension et fonctionne avec PHP 4 et PHP 5.
Installation de la librairie
Déclaration
Les bases d'un fichier pdf
Création/ouverture du fichier
Instantiation avec 3 paramètres de base : new PDF('type portrait(P ou L pour paysage)','unité de référence des mesures (mm ou autre)','format A4 (ou autre)')
Exemple : $PDF = new PDF('P','mm','A4'); pour instancier un fichier de type portrait, avec des unités en mm et au format A4
Fermeture du fichier
$PDF->Output(Paramètre 1,Paramètre 2);
paramètre 1 : Nom du fichier. Avec son répertoire (si nécessaire pour sauvegarde sur le serveur) si paramètre 2 => F.
paramètre 2 :
F => Enregistrement du fichier dans un répertoire du serveur avec le nom et dans le répertoire définis par le paramètre 1.
D => Prompt utilisateur pour choisir l'ouverture ou la sauvegarde du fichier sur le poste client. Paramètre 1 => nom du fichier.
I => Ouverture automatique dans le navigateur aprés avoir été généré. Paramètre 1 => nom du fichier.
S => Retourne le contenu du fichier pdf sous forme de chaines de caractères. Paramètre 1 => vide.
Exemple $PDF->Output("toto",F); pour enregistrer le document avec le nom 'toto' dans le répertoire courant du serveur.
Element de description du document
Titre
$PDF->SetTitle("Chaine de caractères : titre du document");
Auteur
$PDF->Setauthor("Chaine de caractères : Auteur du document");
Créateur
$PDF->SetCreator("Chaine de caractères : Créateur du document");
Sujet
$PDF->Setsubject("Chaine de caractères : Sujet du document");
Mots-clés
$PDF->SetKeywords("Chaine de caractères : Liste des mot clés du document"); La liste est une suite de mots séparés par des espaces ou une virgule.
Paramétrage général des pages
Saut de page
$PDF->SetAutoPageBreak(paramètre1, paramètre2);
paramètre1 = false => le saut automatique de page n'est pas activé, true => saut de page actif
paramètre2 : valeur du reste de marge de bas de page avant d'enclencher le saut de page.
Exemple 1 : $PDF->SetAutoPageBreak(false, 0);
Exemple 2 : $PDF->SetAutoPageBreak(true, 10); pour un saut automatique des pages s'il ne reste plus que 10 mm en bas de page
Les différentes marges sont définies dans les unités définis dans l'instantiation
Exemple : $PDF->SetMargins(5,5,5,5); pour définir une marge de 5 mm
Couleur du texte
Fixe la couleur pour le texte. Elle peut être indiquée en composantes RGB ou en niveau de gris. La
méthode peut être appelée avant que la première page ne soit créée et la valeur est conservée de page
en page. La méthode peut aussi être appelée pour changer ponctuellement la couleur d'un texte particulier.
param1 (r) : Si g et b sont renseignés, composante de rouge; sinon, indique le niveau de gris. Valeur comprise entre 0 et 255.
param2Optionnel (g) : Composante de vert (entre 0 et 255).
param3Optionnel (b) Composante de bleu (entre 0 et 255).
Exemple : $PDF->SetTextColor(0); pour définir la couleur noire pour le texte.
Police de caractères
Fixe la police utilisée pour imprimer les chaînes de caractères. Il est obligatoire d'appeler cette
méthode au moins une fois avant d'imprimer du texte, sinon le document résultant ne sera pas valide.
La police peut être soit une police standard, soit une police ajoutée à l'aide de la méthode AddFont().
Les polices standard utilisent l'encodage Windows cp1252 (Europe de l'ouest).
La méthode peut être appelée avant que la première page ne soit créée et la police est conservée de
page en page.
Note : pour les polices standard, il est nécessaire que les fichiers de métrique soient accessibles. Il y a trois possibilités pour cela :
Ils sont dans le répertoire courant (celui du script en cours d'exécution)
Ils sont dans un des répertoires définis par le paramètre include_path
Ils sont dans le répertoire défini par la constante FPDF_FONTPATH
Exemple dans notre cas : define('FPDF_FONTPATH','phptopdf/font/');
Note : Si le fichier correspondant à la police demandée n'est pas trouvé, l'erreur "Could not include font metric file" est générée.
$PDF->SetFont(parametre1,parametre2,parametre3)
parametre1 : Famille de la police. Il peut s'agir d'un nom défini par AddFont() ou bien d'une desfamilles standard :
Courier(caractères de largeur fixe)
Helvetica ou Arial(synonymes; sans serif)
Times (avec serif)
Symbol (symboles)
ZapfDingbats (symboles)
Note :Le nom n'est pas sensible à la casse.
Il est également possible de passer une chaîne vide, auquel cas la famille courante est
conservée.
parametre2 : Style de la police. Les valeurs possibles sont (indépendamment de la casse). Chaîne vide : normal
B : gras
I : italique
U : souligné
Combinaison quelconque comme par exemple "BI" pour gars, italique. La valeur par défaut est le style normal. Les styles gras et italique ne s'appliquent pas aux familles Symbol et ZapfDingbats
parametre3 : Taille de la police en points. La valeur par défaut est la taille courante. Si aucune taille n'a encore été spécifiée depuis le début du document, la valeur prise est 12.
Exemple : $PDF->SetFont("Arial",'B',15); pour une police de type Arial en gras et de 15
Ecriture d'un texte
Il existe plusieurs méthodes pour écrire du texte :
La méthode Write(Hauteur de la ligne,Chaîne à imprimer,link) : imprime du texte à partir de la position courante. Lorsque la marge droite est atteinte
(ou que le caractère \n est rencontré), un saut de ligne est effectué et le texte continue à partir de la
marge gauche. Au retour de la méthode, la position courante est située juste à la fin du texte.
La méthode Text(Abscisse de l'origine,Ordonnée de l'origine,Chaîne à imprime) imprime une chaîne de caractères. L'origine est à gauche du premier caractère, sur la ligne de base.
Cette méthode permet de positionner précisément une chaîne dans la page.
La méthode Cell()
Style du document
Insérer une image
Saut de page
Entête est bas de page
Numérotation des pages
Fond de page
Construction de tableaux
Exemple
Le but est de présenter sous forme d'un fichier PDF le résultat d'un DIR (listage de répertoires, sous-répertoires et fichiers) de la partie PHP de monwebfacile. Le fichier est automatiquement créé lorsque l'on clique sur la commande getDIR.
Télécharger un fichier (download)
Il peut être utile d'avoir un bouton sur son site pour pouvoir télécharger un fichier particulier. Ce bouton peut prendre la forme d'une boite de sélection, d'un lien hypertexte ou autre.
Principe
Remarques sur le PHP
Le plus important est d’ajouter les bonnes en-têtes au document pour que le navigateur interprète correctement les données reçues.
"Content-Disposition" pour forcer le dialogue de sauvegarde (dialogue qui s'ouvre lorsque vous demandez le téléchargement et vous propose d'ouvrir ou de sauvegarder le fichier) et fournir une information (en principe un nom de fichier par défaut), à afficher dans le dialogue de sauvegarde.
Attention le nom du fichier :
ne doit pas contenir de carctères spéciaux: < > \ " / : | ? * espace.
ne doit pas être référencé avec un chemin d'accés (uniquement le nom et son extension).
doit théoriquement être entre double quotes, mais la plus part des navigateurs acceptent sans double quotes.
"Content-Transfer-Encoding" pour faciliter le transport d'informations via different protocoles (exp RFC 821 restreint les messages mail à 7-bit US-ASCII). Il définit un ensemble de méthodes pour représenter des données binaires sous forme de texte ASCII. L'en-tête MIME « Content-Transfer-Encoding » indique la méthode utilisée.
"Content-Type" indique le type de média internet (type MIME) du contenu du message, consistant en un type et un sous-type ( exp : « Content-Type: text/plain »).
"Content-Length" indique la longueur du fichier au dialogue de sauvegarde.
"Pragma: no-cache", "Cache-Control: must-revalidate, public", "Expires: 0" pour ne pas mettre en cache le fichier transféré lors de la réception.
"Pragma: no-cache" : permet au navigateur d'indiquer au cache de récupérer le document auprès du serveur d'origine plutôt que de lui renvoyer celui qu'il conserve.
"Cache-Control: must-revalidate, public" : must-revalidate force le cache à se reconnecter au serveur avec un If-Modified-Since (y at'il eu une modification depuis ..).
Cache-control comporte souvent les mentions post-check=0, pre-check=0 : il faut savoir que si ces deux directives sont initialisées à 0 elles sont totalement ignorées, il n'est donc pas nécessaire de les faire apparaître.
public => la réponse peut être mise en cache par n'importe quel cache. Private => la réponse est destinée à un client unique et ne doit pas être mis en cache par un cache partagé. Un serveur proxy ne doit pas mettre en cache la réponse bien qu'un client puisse le faire.
"Expires: 0" : cette directive indique aux caches pour combien de temps la donnée associée reste fraîche. Après échéance, les caches vérifieront toujours auprès du serveur original si le document a changé.
readfile() lit le fichier et l'envoie dans le buffer de sortie.
Envoyer un fichier (upload)
But
Le but est de sélectionner à partir d'un formulaire, un ou des fichiers du disque dur pour les transférer vers un serveur distant. Les contrôles de taille (< 500000k), type (jpeg uniquement), dimension (hauteur > 100px) ainsi que le préview sont basés sur l'API File de HTML5. Ces contrôles sont utilisés à titre didactique pour montrer comment exploiter ces informations. Le bouton effacer permet d'effacer localement la sélection du fichier.
Avertissement
Les serveurs PHP Apache limitent la dimension des fichiers en upload et download à 2 Mo.
On peut vérifier cela par un phpinfo().
Deux solutions si vous n'êtes pas propriétaire du serveur (mais ça ne marche pas à tous les coups !!):
Par exemple pour augmenter ces tailles à 10 Mo => rajouter dans le fichier htaccess :
SetEnv upload_max_filesize 10M
SetEnv post_max_size 10M
Si votre hébergeur a activé le mode suPHPV (Note1), allez dans le dossier où est localisé le script, créez un fichier que l'on nommera php.ini, avec pour contenu :
upload_max_filesize = 10M
post_max_size = 10M
Note1 : suPHP est un outil pour exécuter des scripts PHP mais en utilisant des permissions paramétrées par l'utilisateur (on se substitue aux permissions du serveur). Cela consiste en un module Apache (mod_suphp) et une "setuid root binary" (suphp voir Note2) qui est appelée par Apache pour changer l'uid ( identifiants du ou des propriétaires) du process qu'exécute l'interpréteur PHP.
Note2 : suphp vient d'UNIX et concerne les droits d'accés permettant à des utilisateurs de dérouler un exécutable avec leurs propres droits.
Mécanismes utilisés
Cet exercice va nous permettre d'aborder plusieurs sujets dont certains que nous avons déjà vus dans des fiches précédentes :
L'attribut multipart/form-data du formulaire pour spécifier que l'on enverra des données binaires (fichier) et du texte (champs de formulaire). Indispensable dans les cas de tranfert de fichiers.
L'utilisation de la balise <input> dans un environnement multifichiers :
l'attribut multiple pour autoriser la sélection de plusieurs fichiers : multiple="multiple"
l'attribut name sous forme de tableau pour identifier une sélection de plusieurs fichiers : name="n_files[ ]"
L'attribut HTML accept qui permet de spécifier des types MIME pour l'envoi d'un fichier. Exemple accept="text/html,text/plain"
Dans l'exemple ci-contre accept="image/jpeg" permet lors de la recherche des fichiers de pouvoir sélectionner uniquement les fichiers de type jpeg. On remarquera toutefois que la sélection de tous les fichiers existe aussi dans le choix (*.*) donc rien n'empêche de sélectionner un autre type de fichier (gif par exemple) et de tenter de le télécharger. C'est la raison pour laquelle il faut faire le test dans le code avant l'envoi.
Exemple <input type="file" id="files" name="n_files[ ]" accept="image/jpeg,image/gif,image/png" multiple="multiple" />
La personnalisation de la balise <input>
la mise en oeuvre de l'API FileReader pour prévisualiser les fichiers avant de les transférer. Le principe de cette API a été décrit dans la fiche JVS_HTML5 rubrique "Lecture de fichiers locaux : API Files".
Une barre de progression lors du chargement des fichiers locaux. Exemple déjà vu ICI.
Principales méthodes
Deux méthodes générales sont à notre disposition pour transférer les données vers le serveur une fois que l'on a a validé le formulaire. Les deux actions utilisent la méthode POST (car cette requête n'a aucune restriction sur le nombre de données transmises), mais l'une nécessite en fin de traitement le rechargement de la page appelante (méthode post classique), alors que l'autre agit de manière totalement transparente sans avoir à recharger la page (méthode AJAX).
Les informations du formulaire sont reçues dans la page PHP sous forme de tableaux (superglobal) $_POST pour les champs textuels (text, checkbox, select, textarea, ...), et $_FILES pour les informations concernant les champs de type file.
Les fichiers sont temporairement placés dans le dossier temporaire du serveur.
Upload : méthode POST classique
L'exemple consiste à utiliser un formulaire (method="post") pour transférer un fichier dans le serveur via un appel à une page PHP. Lorsque le processus est terminé la page PHP rappelle le formulaire avec des informations par la méthode GET (paramètres dans l'URL) sur le résultat (ok ou non) et le nom du fichier qui a été enregistré.
Remarques sur le code du formulaire
Remarques sur le code PHP
Les données de fichier transférées sont disponibles dans le tableau $_FILES[][] référencé par l'élément 'n_files' du formulaire :
$_FILES['n_files']['name']; donne le nom du fichier.
$_FILES['n_files']['type']; donne le type MIME du fichier.
$_FILES['n_files']['size']; donne la taille du fichier.
$_FILES['n_files']['tmp_name']; donne l'emplacement temporaire du fichier dans le serveur.
$_FILES['n_files']['error']; donne des informations si une erreur survient lors du transfert :
$_FILES['n_files']['error'] == UPLOAD_ERR_NO_FILE : pas de fichier disponible.
$_FILES['n_files']['error'] == UPLOAD_ERR_INI_SIZE : fichier dépassant la taille maximale autorisée par PHP.
$_FILES['n_files']['error'] == UPLOAD_ERR_NO_TMP_DIR : le dossier temporaire est manquant.
$_FILES['n_files']['error'] == UPLOAD_ERR_CANT_WRITE : échec de l'écriture du fichier sur le disque du serveur.
$_FILES['n_files']['error'] == UPLOAD_ERR_EXTENSION : une extension PHP a arrêté l'envoi de fichier.
file_exists() et mkdir() créent le répertoire de sauvegarde définitif.
move_uploaded_file() transfère le fichier du répertoire temporaire vers le répertoire définitif.
header ("Location:".$adrRetour."?imgErr=false&nomFile=".$uploadNameFile); retourne à la page appelante avec comme informations supplémentaires imgErr false ou true suivant le résultat du tranfert et nomFile comme nom du fichier stocké sur le serveur.
Exemple de traitement pour un seul fichier avec préview
Exemple général avec possibilités d'upload de fichiers multiples
Upload : méthode AJAX
Par souci de clarté la base du code utilisé est celui de l'exemple général avec possibilités d'upload de fichiers multiples détaillé ci-dessus et qui a été fortement allégé de toutes fioritures (barre de progression lors du chargement local et possibilité de consulter les fichiers distants). De même pour la partie PHP : supression de l'analyse détaillée des erreurs, des caractéristiques des fichiers récupérés ainsi que la partie retour des résultats.
Modifications de la partie formulaire
Le formulaire lui même
onsubmit et action n'ont plus à être renseignés car la connexion se fait au travers de la reqête AJAX
Utilisation de FormData.append ()
FormData.append () est la méthode utilisée pour manipuler des fichiers, blobs ou des chaines de caractères. Il permet de présenter les données sous forme d'objet exploité par le formulaire pour le transfert d'informations vers le serveur.
En fonction des objets à manipuler les syntaxes suivantes sont à appliquer :
formData.append(name, file, filename); pour des fichiers.
formData.append(name, blob, filename); pour des blobs : type de donnée permettant le stockage de données binaires (le plus souvent des fichiers de type image, son ou video) dans le champ d'une table d'une base de données.
formData.append(name, value); pour des chaines.
Le premier paramètre (name) spécifie le nom de l'entrée de données (files[] dans notre formulaire).
Le deuxième paramètre spécifie s'il s'agit d'un type fichier (f = files[i] dans notre formulaire), blob, ou chaine qui sera utilisée comme valeur pour l'entrée de données.
Dans le cas de type fichier ou blob on peut spécifier un nom de fichier comme paramètre optionnel.
var content = '<a id="a"><b id="b">hello!</b></a>'; // Le corps d'un fichier html.
var blob = new Blob([content], { type: "text/xml"});
formData.append("webmasterfile", blob);
Note: The fields "webmasterfile" contient un fichier. Le nombre relatif au champ "numTelephone" assigned to the field "accountnum" est immédiatement converti en chaine de caractères "0123456789" par la méthode FormData.append(). Le champ valeur peut être un Blob, un Fichier, ou une chaine: Si la valeur est ni un Blob ou un Fchier, la value est immédiatement convertie en chaine de caractères.
Ce qui se traduit dans notre cas :
Initialisation d'une variable globale
Insertion de formData.append dans la boucle d'analyse des fichiers
Requête AJAX
Variables globales
Envoi des données
Remarque event.preventDefault() : Un événement est un changement d'état de l'environnement qui peut être intercepté
par le code JavaScript. Dans certains cas, l'action implicite (par défaut)
correspondante est alors annulable : il est par exemple possible d'empêcher que
l'activation d'un lien entraîne la navigation vers l'URL associée.
Pour les types d'événements qui l'autorisent, il est possible grâce à cette
méthode d'annuler l'action implicite correspondante. Par exemple,
l'action implicite associée à un événement de type submit est l'envoi au
serveur du formulaire concerné.
Supervision de la réponse
Modification de la partie PHP
Pas de changement fondamental, si ce n'est l'allègement du code. La requête renvoie
'nonOK' si une erreur est survenue : if($erreurUpload) echo 'nonOK';
'OK' si la requête s'est déroulée sans problèmes : if($erreurUpload) echo 'OK';
Exemple complet
Cas d'un serveur FTP
Attention : Les serveurs du FAI Free (ainsi que d'autres d'ailleurs) n'acceptent pas la fonction ftp_connect(). Ce qui suit est alors purement indicatif et on ne pourra pas faire d'exemples pratiques.
Le serveur FTP
Echanges
Le mode classique
« FTP » signifie File Transfer Protocol (protocole de transfert de fichiers) et sert à faire transiter des fichiers entre un serveur et un client. C'est un protocole (parmi tant d'autres) très utilisé qui est, en général, associé au port 21.
Le mode sécurisé
La connexion est réalisée en mode SSL (Secure Socket Layer). SSL est un protocole de sécurisation des échanges, développé par Netscape. Il a été conçu pour assurer la sécurité des transactions sur Internet (notamment entre un client et un serveur) et il est intégré depuis 1994 dans les navigateurs.
Lorsque l'on utilise une connexion SSL, on ne parle plus de FTP mais de FTPS : File Transfer Protocol over SSL
Les méthodes disponibles
ftp_connect() ou ftp_ssl_connect() : Ouverture d'une connexion (éventuellement sécurisée) FTP avec le serveur.
Définition
La fonction ftp_connect() retourne une ressource FTP qui va servir au maniement des fichiers en cas de succès, ou FALSE si une erreur survient.
Syntaxe
$ftp_stream = ftp_connect("host", port , timeout); ou $ftp_stream = ftp_ssl_connect("host", "port" , timeout);
Paramètres
Description
host
Chaine de caractères comme adresse du serveur FTP. Ce paramètre ne doit jamais avoir de slash final et ne doit pas être préfixé par ftp://.
port
Spécifie un numéro de port alternatif pour la connexion. S'il est omis ou définie à zéro, alors le port par défaut utilisé sera 21.
timeout
Spécifie le délai de connexion pour toutes les opérations de sous séquences du réseau. S'il est omis, la valeur par défaut sera 90 secondes. Le délai de connexion peut être modifié et interrogé à n'importe quel moment avec les fonctions ftp_set_option() et ftp_get_option().
Exemple
$ftp_stream = ftp_connect("ftpperso.free.fr", 21,90) or exit('Erreur : connexion au serveur impossible.');
$ftp_stream = ftp_ssl_connect("ftpperso.free.fr", 21,90) or exit('Erreur : connexion sécurisée au serveur impossible.');
ftp_login() : Identification aprés l'ouverture de la connexion FTP.
Définition
Il faut obligatoirement être identifié pour pouvoir interagir avec le serveur FTP. La fonction retourne TRUE en cas de succès ou FALSE si une erreur survient. Si l'identification échoue, PHP lancera une alerte.
Syntaxe
ftp_login($ftp_stream,$username,$password);
Paramètres
Description
$ftp_stream
Identifiant de la connexion FTP renvoyé par la fonction ftp_connect().
$username
Nom de l'utilisateur de la connection FTP.
$password
Mot de passepour accéder à la connection FTP.
Exemple
$login_result = ftp_login($ftp_stream,"monNom","monMDP") or exit('Erreur : Identification impossible.');
ftp_close() : Fermeture de la connexion FTP.
Définition
Ferme la connexion ftp_stream et libère les ressources. La fonction retourne TRUE en cas de succès ou FALSE si une erreur survient. Si l'identification échoue, PHP lancera une alerte.
Syntaxe
ftp_close($ftp_stream);
Exemple
$close_result = ftp_close($ftp_stream) or exit('Erreur : Fermeture de la connexion impossible.');
ftp_nlist() : Lister les fichiers sur le serveur.
Définition
Retourne un tableau avec le nom de tous les fichiers.
Identifiant de la connexion FTP renvoyé par la fonction ftp_connect().
repertoire
Le dossier à lister. Ce paramètre peut également inclure des arguments, e.g. ftp_nlist($conn_id, "-la /your/dir"); Notez que ce paramètre n'est pas échappé, il peut donc y avoir des comportements non-désirés si le nom des fichiers contient des espaces ou d'autres caractères. Si "repertoire" = "." signifie que l'on travaille sur le dossier actuel.
Exemple
ftp_put() : Envoyer un fichier vers le serveur.
Définition
Enregistre un fichier local sur le serveur FTP et écrase le fichier existant. Retourne TRUE ou FALSE suivant que la fonction aboutit ou est en erreur. 550 : fichier ou répertoire inexistant ou accés non autorisé
Requis. Specifie le mode de transfert. Valeurs possibles :
ASCII : L'intérêt du mode ASCII et d'éviter les problèmes de compatibilités dues aux différences de gestion des fin de ligne (EOL) selon les systèmes d'exploitation. En général cela ne pose pas de problème, mais c'est plus propre de respecter les conventions du système hôte. En mode ASCII, le client FTP va modifier le format des retours chariot en fonction du système d'exploitation du client et du serveur. Sur Windows, les retours chariot seront composé de 2 caractères : retour chariot et nouvelle ligne : \r\n
BINARY : Le mode binary est le plus simple à comprendre. Il transfère le fichier sur le serveur sans le modifier, ainsi les fichiers uploadé ou downloadé en mode Binary sont identiques à l'octet près entre le client et le serveur.
AUTO, le client FTP va automatiquement choisir le mode Binary ou le mode ASCII en fonction de l'extension du fichier. Les fichiers qui contiennent du texte (comme les fichiers .txt, .php, .css, .js, .sql...) seront transféré en mode ASCII, tandis que les autres fichiers (images .jpg, .png, vidéos .mp4...) seront transférés en mode Binary.
startpos
Optionnel. Specifie la position dans le fichier distant pour démarrer l'upload.
Exemple
$put_result = ftp_put(ftp_stream,"fichier destinataire","mon fichier","AUTO") or exit('Erreur : Transmission du fichier impossible.');
ftp_get() : Recevoir un fichier du serveur.
Définition
Télécharger un fichier du serveur FTP. Retourne TRUE ou FALSE suivant que la fonction aboutit ou est en erreur. 550 : fichier ou répertoire inexistant ou accés non autorisé
Syntaxe
$get_result = ftp_get(ftp_stream,"dossier où envoyer","fichier à télécharger",mode);
Paramètres
Description
ftp_stream
Identifiant de la connexion FTP.
fichier distant
Requis. Specifie l'adresse du fichier distant.
fichier local
Requis. Specifie le path du fichier à uploader.
mode
Requis. Specifie le mode de transfert. Valeurs possibles : FTP_ASCII ou FTP_BINARY.
Exemple
$get_result = ftp_get(ftp_stream,"mon répertoire destinataire","mon fichier sur le serveur","AUTO") or exit('Erreur : Réception du fichier impossible.');
ftp_pasv Active ou désactive le mode passif
Définition
Si la connexion au serveur FTP passe par un Firewall ou un NAT (chez le client, ou au niveau du client). Dans ce cas, il faut activer le mode passif, pour éviter des problèmes lors des manipulations avec le serveur FTP (par exemple, pour la fonction ftp_nlist).
En mode actif, c'est le client FTP qui va déterminer le port à utiliser et le serveur FTP qui initialisera la connexion.
En mode passif, c'est le serveur FTP qui va déterminer le port à utiliser et le client FTP qui initialisera la connexion. Ce mode est le mode recommandé.
Cette fonction retourne TRUE en cas de succès ou FALSE si une erreur survient.
On dispose d'autres fonctionnalités interressantes en particulier :
Codage base 64
C'est quoi?
Le codage base 64 est un codage permettant de transformer toute donnée binaire
en une donnée n’utilisant que les 64 caractères ASCII disponibles sur la plupart
des systèmes informatiques, et acceptés par les protocoles de transmission de
messages (courrier électronique), ou encore pour les photos des formats VCF (contacts).
Tout fichier texte ou image peut être transformé en une combinaison des caractères suivants : les 26 caractères A-Z, les 26 caractères a-z, les 10 caractères 0-9 et les caractères + et / soit 26+26+10+2 = 64 d'ou le nom de codage base 64.
Mécanisme d'encodage
Quelques rappels
Le bit : c'est l'unité la plus simple dans un système de numération, ne pouvant prendre que deux valeurs, désignées le plus souvent par les chiffres 0 et 1.
L'octet ou byte: c'est le regroupement de 8 bits pour coder une information. Le bit de poids faible est celui situé le plus à droite. Ce système binaire permet de représenter des valeurs entre 0 et 255.
00000000 est un octet de valeur 0 (tous les bits sont à 0).
00000001 est un octet de valeur 1 (le bit de poids faible est à 1).
00100000 est un octet de valeur 32.
10000000 est un octet de valeur 128.
10100010 est un octet de valeur 162 (bit de pois 128 + bit de poids 32 + bit de poids 2).
Quelques déclinaisons de l'octet :
1 kilo-octet (ko) = 1 024 octets,
1 mégaoctet (Mo) = 1 024 ko = 1 048 576 octets,
1 gigaoctet (Go) = 1 024 Mo = 1,073 milliard d'octets ...
Le Word : est un ensemble de 16 bits (2 octets). On trouve aussi le double word (4 octets) etc ..
La notation hexadécimale (base 16)
On a souvent recours à la base 16 ou notation hexadécimale pour éviter d'avoir des représentations de nombre binaires à rallonge. La base 16 utilise 16 chiffres mais comme notre numération ne sait en représenter que 10 (0-9), on utilise les lettres de A à F pour aller de 10 à 16. On coupe l'octet, le word ou le double word en tranche de 4 bits (16 valeurs) que l'on va représenter en valeur hexadécimale :
l'octet 00100000 fractionné en 4 bits va donner 2 groupes : 0010 et 0000. Chaque groupe codé en héxadécimal va donner pour valeur : 20.
l'octet 10100010 fractionné en 4 bits va donner 2 groupes : 1010 et 0010. Chaque groupe codé en héxadécimal va donner pour valeur : A2 (A pour la valeur 10).
Le codage ASCII
Chaque caractère (octet) possède son équivalent en code numérique sur 1 octet: c'est le code ASCII (American Standard Code for Information Interchange).
Table des codes ASCII étendu
sdfsdfds
Comment lire cette table
Remarque : Un click sur un caractère donne les valeurs décimales et hexadécimales du caractère sélectionné.
Encodage 64bits
Le principe du codage 64bits consiste à découper les données binaires du fichier en tranches de six bits. 6 bits soit 64 combinaisons qui correspondent à l'index dans le jeu de caractères par Base64 (table d'encodage : A-Z, a-z, 0-9, + et/ ).
Pour obtenir les index dans le jeu de caractères les octets du fichier sont fractionnées dans des buffers de 24 bits (3 octets à la fois). Le résultat du buffer est lui même fractionné en 4 paquets de 6 bits chacun, soit 4 index.
Table d'encodage
Sextet
décimal
Code
Sextet
décimal
Code
Sextet
décimal
Code
Sextet
décimal
Code
000000
0
A
000001
1
B
000010
2
C
000011
3
D
000100
4
E
000101
5
F
000110
6
G
000111
7
H
001000
8
I
001001
9
J
001010
10
K
001011
11
L
001100
12
M
001101
13
N
001110
14
O
001111
15
P
010000
16
Q
010001
17
R
010010
18
S
010011
19
T
010100
20
U
010101
21
V
010110
22
W
010111
23
X
011000
24
Y
011001
25
Z
011010
26
a
011011
27
b
011100
28
c
011101
29
d
011110
30
e
011111
31
f
100000
32
g
100001
33
h
100010
34
i
100011
35
j
100100
36
k
100101
37
l
100110
38
m
100111
39
n
101000
40
o
101001
41
p
101010
42
q
101011
43
r
101100
44
s
101101
45
t
101110
46
u
101111
47
v
110000
48
w
110001
49
x
110010
50
y
110011
51
z
110100
52
0
110101
53
1
110110
54
2
110111
55
3
111000
56
4
111001
57
5
111010
58
6
111011
59
7
111100
60
8
111101
61
9
111110
62
+
111111
63
/
Mécanisme
Le principe d'un programme d'encodage consiste à lire dans le fichier source trois octets consécutifs (si il y en a bien encore trois à lire), et écrire dans le fichier de sortie les quatre codes correspondant, et ceci jusqu’à avoir parcouru complètement le fichier source.
Bien entendu si la taille (en octets) du fichier n’est pas un multiple de trois, à la fin du fichier le nombre d’octets réellement lus dans le fichier peut très bien n’être que 1 ou 2.
En effet le codage base 64 code des sextets. Que faire si la donnée à coder n’a pas une longueur multiple de 8 ? La longueur en bits d’un fichier est multiple de 8 mais pas nécessairement multiple de 6. Trois cas de figures peuvent se présenter :
Le fichier à coder a une longueur en bits multiple de 6 : la longueur est
de 6k bits autrement dit k sextets à coder. Dans ce cas chacun des k sextets
est codé, et le fichier codé contient les k codes correspondant à ces k
sextets.
Le fichier à coder a une longueur égale à 6k+2 bits, autrement dit contient
k sextets plus deux bits isolés. À ces deux derniers bits on vient alors
ajouter quatre bits nuls pour former un dernier sextet qui est codé, et on
ajoute à la suite de ce dernier code un double symbole = (qui ne fait pas
partie de l’alphabet cible et qui indique donc que seuls les deux bits de poids
forts du code précédent les deux = sont à prendre en compte pour le décodage).
Le fichier à coder a une longueur égale à 6k+4 bits, autrement dit contient
k sextets plus quatre bits isolés. À ces quatre derniers bits on vient alors
ajouter deux bits nuls pour former un dernier sextet qui est codé, et on ajoute
à la suite de ce dernier code un simple symbole = (qui ne fait pas partie de
l’alphabet cible et qui indique donc que seuls les quatre bits de poids forts
du code précédent le = sont à prendre en compte pour le décodage).
Lire un fichier codé en 64bits
Syntaxe générale
"data:typeMime;base64,Contenu du fichier"
Pour des images
<img src="data:image/jpg;base64,/9j/4AAQSkZJRgABAQE.........." alt="aperçu d'une image encodée en base64" />
<img src="data:image/gif;base64,/9j/4AAQSkZJRgABAQE.........." alt="aperçu d'une image encodée en base64" />
<img src="data:image/png;base64,/9j/4AAQSkZJRgABAQE.........." alt="aperçu d'une image encodée en base64" />
Une image générée en base 64 ne peut pas être mise en cache par le navigateur,
Les images doivent être de tailles raisonnables au risque d'alourdir le chargement et la navigation. A titre d'exemple un fichier encodé devient plus lourd d'environ 33%,
L'encodage de fichier css ou javascript donne des fichiers carrément illisibles.
Ce codage est trés pratique lorsque l'on veut créer des fichiers de types cartes de visite (vcf) et que l'on désire y inclure une petite photo.
Exemple
L'exemple suivant va nous montrer un fichier image gif (qui peut être aussi un gif animé) dans sont format classique et dans son format codage 64bit.
Les métadonnées servent à décrire ou à définir toutes sortes de données comme des fichiers image, texte, son ou vidéo mais aussi des photos. Dans ce chapître on se limitera aux fichiers de type image, mais le principe général pourra être appliqué à d'autres fichiers comme par exemples les fichiers son que nous verrons dans le chapître suivant.
Méta données EXIF
EXIF pour exchangeable image file format, concerne les informations relatives à la caméra qui a pris la photo ainsi que les différents réglages associés (des iformations fixes comme par exemple le modèle de caméra utilisée, et aussi des informations dynamiques relatives aux prises de vues comme par exemple l'orientation, l'ouverture, la vitesse etc ...). Ces informations sont stockées dans l'image lors de la prise de vue.
Ce format de métadonnées n’est pas standardisé, il est toutefois utilisé par de nombreux constructeurs d’appareils photographiques numériques.
Noms des champs
Commentaires
FileName
Nom du fichier
FileName
Nom du fichier
FileDateTime
Date fichier
FileSize
Taille
FileType
Type
MimeType
Type mime
SectionsFound
Sections
ImageDescription
Description de l'image
Make
Fabricant
Model
Modèle
Orientation
Orientation
XResolution
Résolution en X
YResolution
Résolution en Y
ResolutionUnit
Unité pour la résolution
Software
Logiciel
DateTime
Date de modification
Artist
Artiste
YCbCrPositioning
Positionnement YCbCr
Copyright
Droit de copie (Copyright)
ExposureTime
Temps d'exposition (s)
FNumber
Nombre-F
ExposureProgram
Programme d'exposition
ExifVersion
Version EXIF
DateTimeOriginal
Date et Heure d'origine
DateTimeDigitized
Date et heure numérisée
ComponentsConfiguration
Configuration des composantes
CompressedBitsPerPixel
Bits par pixel compressé
ExposureBiasValue
Valeur compensation Exposition
MaxApertureValue
Ouverture maxi.
MeteringMode
Mode calcul exposition
LightSource
Source lumière
Flash
Flash
FocalLength
Longueur de focale (mm)
UserComment
Encodage commentaires
SubSecTime
Heure fractions de sec.
SubSecTimeOriginal
Heure d'origine fractions sec.
SubSecTimeDigitized
Heure numérisée fractions sec.
FlashPixVersion
Version FlashPIx
ColorSpace
Mode de couleur(BPP)
ExifImageWidth
Largeur de l'image
ExifImageLength
Hauteur de l'image
InteroperabilityOffset
Position interopérabilité
SensingMethod
Méthode capteur
FileSource
Source du fichier
SceneType
Type de scène
CustomRendered
Rendu personnalisé
ExposureMode
Mode exposition
WhiteBalance
Equilibrage des blancs
DigitalZoomRatio
Gros plan numérique
FocalLengthIn35mmFilm
Longueur de focale (35mm)
SceneCaptureType
Type de capture de scène
GainControl
Contrôle des gains
Contrast
Contraste
Saturation
Saturation
Sharpness
Netteté
SubjectDistanceRange
Plage de distance du sujet
JPEGInterchangeFormatLength
Taille de la vignette
JPEGInterchangeFormat
Décalage de la vignette
InterOperabilityIndex
Index IOP
InterOperabilityVersion
Version IOP
Les métadonnées IPTC
L'IPTC définit un standard pour stocker des informations relatives à une image. Ces informations peuvent être le nom de l'image, le titre de l'image, des mots-clés associés à l'image, l'auteur de l'image, le copyright... Elles permettent de décrire l'image. Les données IPTC font partie du fichier. Elles sont dans l'image et de ce fait on peut manipuler l'image sans perdre ces informations.
Attention : Les métadonnées IPTC n'existent que dans les images aux formats jpg, jpeg et tiff. Le métadonnées ne sont pas pour autant exclusives à ces formats. Les images au format png par exemple possèdent d'autres types de métadonnées.
Les métadonnées IPTC sont constituées d'un certain nombre de sous métadonnées stockées dans le fichier lui-même.
Ref sous métadonnées
Noms des champs
Commentaires
000
version enregistrement
005
Object Name
Nom de l'objet.
007
Edit Status
Statut éditorial.
010
Urgency
Priorité - 0 à 8 -.
015
Category
Catégorie.
020
Supplemental Category
Categories supplémentaires.
022
Fixture Identifier
Identifiant.
025
Keywords
Mots clé.
026
Location
localisation.
030
Release Date
Date sortie/disponibilité.
035
Release Time
Heure sortie/disponibilité.
040
Special Instructions
Instruction spéciale.
045
Reference service
Service de référence (associé avec les champs 47 et 50).
047
Reference Date
Date de référence.
050
Reference Number
Numéro de référence.
055
Date Created
Date création.
060
Time Created
Heure de création.
065
Originating Program
Programme d'origine.
070
Program version
Version du programme.
075
Object cycle
Cycle de l'objet - a = matin, b = après midi, c = soir -.
080
By-line
Créateur.
085
By-line Title
Titre du créateur.
090
City
Ville.
092
Région.
095
Province/State
Province/état.
101
Country/Primary Location Name
Pays.
103
Original Transmission Reference
Référence de la transmission (otr).
105
Headline
Entête/titre.
110
Credit
Source/fournisseur de l'objet.
115
Source
Source photo (propriété intellectuelle).
116
Copyright Notice
Copyright.
118
Contact
Contact.
120
Caption/Abstract
Légende/résumé.
122
Writer/Editor
Auteur.
130
Image Type
Type de l'image.
Décodage des tag Images jpeg
Les informations contenues dans l'image sont récupérées avec la fonction GetImageSize qui peut retourner plus d'informations dans le paramètre optionnel sous forme de tableau associatif (getimagesize(fichier,paramètre optionnel)). Dans cette variable seront stockés entre autres les champs IPTC non vides, en fait particulièrement le marker APP13 défini par Adobe Photoshop et l'IPTC pour un fichier JPEG, mais aussi d'autres markers que nous n'aborderons pas dans ce propos.
PHP met à notre disposition plusieurs méthodes pour lire les tags
Les tags IPTC du marqueur APP13
La méthode iptcparse()
Les tag EXIF
La méthode exif_read_data()
Lit les en-têtes EXIF des images JPEG et TIFF. Avec cette fonction, on peut lire les données méta générées par les appareils photos numériques.
Décodage des tag Images png
Les fichiers PNG ont dans leurs spécifications la possibilité d'intégrer une zone de commentaires chunk compressée et donc illible sans programme adapté.
Le format des fichiers PNG se compose d'une part d'une entête et d'autre part de multiples block de données communément appelés CHUNK.
Chaque chunk est composé de 4 parties :
Sa taille : un entier non signé de 4 octets, décrivant la taille du segment.
Son type : 4 caractères (4 octets) composés de caractères ASCII alphanumériques (A-Z, a-z, 65 à 90 et 97 à 122) permettant de qualifier la nature du chunk.
Les données elle mêmes.
Un CRC (cyclic redundancy check) sur 4 octets pour vérifier l'intégrité du chunk.
Les chunks peuvent être présents dans n'importe quel ordre, toutefois le premier doit être le chunk IHDR et le dernier le chunk IEND.
L'entête
8 caractères héxa : \x89PNG\x0d\x0a\x1a\x0a
Les principaux Chunk
Chunks
Contenu
Commentaires
IHDR
Largeur (4 bytes)
Hauteur ( 4 bytes)
Nombre de bits par échantillon ( 1 byte)
Type de couleur (1 byte) => 1 (palette), 2 (color), 4 (alpha channel)
Méthode de compression (1 byte)
Méthode filtrage (1 byte)
Méthode interface (1 byte)
Entêtes de l'image.
PLTE
Rouge: 1 byte (0 = noir, 255 = rouge)
Vert: 1 byte (0 = noir, 255 = vert)
Bleu: 1 byte (0 = noir, 255 = bleu)
Palette. Nécessaire si le type de couleur et égal à 3 (indexed color). De 1 à 256 entrées palette avec 3 informations (3 byte) par palette.
cHRM
White Point x: 4 bytes
White Point y: 4 bytes
Red x: 4 bytes
Red y: 4 bytes
Green x: 4 bytes
Green y: 4 bytes
Blue x: 4 bytes
Blue y: 4 bytes
Chromaticités du rouge, vert, et bleu utilisés.
tEXt
Les chunks iTXt, tEXt, et zTXt sont utilisés comme informations textuelles associées à l'image.
Chaque text chunk est structuré par un mot clé qui indique le type d'information concernée par le texte associé. Les mots clé suivants sont prédéfinis :
Mots clé
Textes
Title
Court texte pour le titre de l'image.
Author
Auteur.
Description
Description de l'image.
Copyright
Copyright.
Creation Time
Date de création
Software
Logiciel utilisé pour créer l'image.
Disclaimer
Avertissement légal.
Warning
Avertissement lié à la nature du contenu.
Source
Appareil utilisé pour la prise de vue.
Comment
Commentaire divers; Conversion de commentaire de GIF
Structure :
Mot clé : 1-79 bytes (caractere)
Séparateur (Null) : 1 byte
Texte : n bytes (caractere)
iTXt
Les chunks iTXt, tEXt, et zTXt sont utilisés comme informations textuelles associées à l'image.
Chaque text chunk est structuré par un mot clé qui indique le type d'information concernée par le texte associé. Les mots clé suivants sont prédéfinis :
Ce chunk is sémantiquement équivalent à equivalent aux chunks tEXt et zTXt, mais au format d'encodage UTF-8. Sa structure est définie de la façon suivante :
Mot clé : 1-79 bytes (caractere)
Séparateur (Null) : 1 byte
Compression flag : 1 byte
Méthode de compression : 1 byte
Language : 0 ou plusieurs bytes (caractere)
Séparateur (Null) : 1 byte
Translated keyword: 0 ou plusieurs bytes
Séparateur (Null) : 1 byte
Text : 0 ou plusieurs bytes
zTXt
Les chunks iTXt, tEXt, et zTXt sont utilisés comme informations textuelles associées à l'image.
Chaque text chunk est structuré par un mot clé qui indique le type d'information concernée par le texte associé. Les mots clé suivants sont prédéfinis :
Ce schuk contient des données textuelles comme tEXt, cependant zTXt profite de la compression. zTXt est recommandé pour stocker de grands blocs de texte. Sa structure est définie de la façon suivante :
Mot clé : 1-79 bytes (caractere)
Séparateur (Null) : 1 byte
Méthode de compression : 1 byte. 0=> Décompressable par gzuncompress()
Texte compressé : n bytes
pHYs
Pixels par unité, X : 4 bytes
Pixels par unité, Y : 4 bytes
Spécification unité : 1 byte
0 : non spécifié
1 : le mètre
Dimensions Physique des Pixels
sRGB
1 Byte d'information
0: Perception
1: Colorimétrie relative
2: Saturation
3: Colorimétrie absolue
Représentativité de l’espace colorimétrique d’un écran
IDAT
Contient les données de l'image.
Un fichier peut contenir plusieurs chunk IDAT. Si c'est le cas, ils doivent apparaître strictement consécutivement.
IEND
Dernière info.
Marque la fin des données du fichier.
Méthode utilisée pour le décodage
Exemple de décodage de tag d'images jpeg et png
Lecture des tags de fichiers audio (mp3 ou ogg)
Généralités
Cette rubrique vous explique comment lire les tag ID3 sans installation d'extensions PECL (PHP Extension Community Library) ou autres.
ID3 est le nom des métadonnées pouvant être insérées dans un fichier audio comme MP3. Ces métadonnées permettent d'avoir des informations sur le contenu du fichier comme le titre, le nom de l'interprète, les commentaires, etc.
Attention : des tag autres que ID3 sont parfois utilisés pour les fichiers MP3 comme le tag APEv1 utilisé avec le Monkey's Audio format. Dans les fichiers MP3,
le tag APE se situe tout à fait en fin de fichier (aprés APETAG), bien séparé du corps du fichier.
Monkey's Audio est à la fois un algorithme et un format de fichier pour des compressions audio sans perte. Monkey's Audio ne rejette pas de données durant la phase d'encodage, comme peuvent le faire des méthodes de compression comme AAC, MP3, Vorbis et Musepack.
structure des tag ID3 pour fichiers de type mp3
structure des tag APE pour fichiers de type mp3
structure des tag ogg pour fichiers de type ogg
Exemple complet et son code php
Explications du code
On va prendre pour exemple un fichier mp3 décodé par un éditeur hexadécimal et dont le début montre des informations concernant les tags id3 et on va détailler le programme PHP pour les lire. Tout d'abord on peut consulter le résultat suivant qui donne les libellés de tag avec leur explications.
0. Chaque traitement de récupération des données est fait au niveau d'une classe spécifique : class ID3TagsReader pour les fichiers mp3 et class oggTagsReader pour les fichiers ogg. Le traitement d'affichage est réalisé par un tronc commun qui fait une boucle sur l'ensemble du répertoire et qui en fonction du type de fichier appelle la classe concernée. On détaillera plus précisément le contenu et le fonctionnement de la classe ID3TagsReader {}.
1. Tout d'abord il faut ouvrir le fichier pour l'exploiter en lecture.
2. On vérifie que l'on a bien affaire à des tag ID3 (3 premiers caractères du fichier).
3. On vérifie la version des Tags (4 ème et 5 ème caractères du fichier) afin d'appliquer les syntaxes de tag correspondant à la version trouvée.
Pour cela bin2hex() convertit des données binaires en représentation hexadécimale.
et hexdec() convertit de hexadécimal en décimal. Soit 3.0 pour notre fichier.
4. Pour chaque Tag ('TIT2', 'TALB', 'TPE1', 'TPE2', 'TRCK', ....), on va voir si ce dernier existe (strpos() != FALSE). S'il existe (toujours avec strpos()) on va déterminer sa position de début dans le fichier et la longueur de son contenu.
strpos ($fichier,$chaine à rechercher,$start) cherche la position de la première occurrence dans une chaîne. Si la chaine à rechercher n'est pas une chaîne, le champ est converti en entier, et utilisé comme caractère de code ASCII correspondant.
Si le paramètre optionnel $start est spécifié, la recherche commencera à partir de ce nombre de caractères compté depuis le début de la chaîne.
strpos() retourne FALSE si l'occurrence n'a pas été trouvée.
La longueur est calculée sur les 3 caractères qui suivent le libellé du tag.
5. On a le départ de la chaine et sa longeur, on va donc pouvoir récupérer les données avec substr(). substr($chaine,$start,$longueur) retourne un segment de chaîne débutant à la position $start et d'une longueur de $longueur.
$iPos+11 car onze octets (4 octets pour le tag et 7 octets pour la longueur de l'information) sépare la position du début du tag de celui du début de l'information.
6. On rajoute une petite analyse de la chaine pour vérifier que les caractères sont valides, et un traitement spécial dans le cas du tag TCON qui peut renvoyer le numéro de genre en lieu et place du libellé : cette information est de la forme "(numéro genre)", on doit donc éliminer les parenthèses pour obtenir un indice exploitable.