Programmation PHP/Fichiers
L'utilisation de fichier peut être utile pour exporter des données à archiver ou accélérer un traitement par un système de cache. Cette page explique comment interagir avec un fichier.
Dossiers
modifierVoici les fonctions usuelles de navigation et manipulation du système de fichier.
Lecture
modifierPHP_OS
: contient de système d'exploitation courant (ex : WINNT, Linux).basename($path)
: extraire le nom du fichier à partir de son chemin.dirname(__DIR__)
: extraire le répertoire parent du dossier en paramètre, au niveau précisé en second paramètre (le parent direct par défaut).chdir($dossier)
: changer de dossier courant ;opendir($dossier)
: ouvrir un dossier ;closedir($dossier)
: fermer le dossier ;is_dir($dossier)
: vérifier la présence d'un dossier ;is_file($fichier)
: vérifier la présence d'un fichier ;file_exists($fichier)
: vérifier la présence d'un fichier ou un dossier local[1] ;filesize($fichier)
: renvoie la taille du fichier en octet[2] ;readdir($dossier)
: lire le contenu du dossier ligne par ligne ;scandir($dossier)
: lire le contenu du dossier en une fois ;glob($regex)
: lire le contenu du dossier courant, avec filtrage regex (ex : *.txt)[3].
Récupérer certains fichiers d'un dossier
modifierPar exemple, pour trouver tous les fichiers .sql du dossier "sql" :
chdir('sql');
$files = glob('*.sql');
var_dump($files);
Écriture
modifiershell_exec('pwd')
: exécuter n'importe quelle commande shell. Le nom du répertoire courant (pwd) dans cet exemple.mkdir()
: créer un dossiertouch()
: créer un fichier (ou le rafraichir s'il existe)rename()
: déplacer un fichier
Les commandes du shell_exec dépendent du système d'exploitation. Par exemple, sur Linux shell_exec('ls')
fonctionne mais sur Windows il renvoie null et il faut utiliser shell_exec('dir')
.
De plus, sachant que les systèmes d'exploitation n'ont pas les mêmes séparateurs de dossiers (sous Windows on utilise "\" et en unixerie c'est "/"), on peut utiliser la constante prédéfinie : DIRECTORY_SEPARATOR
qui fonctionne pour les deux[4].
Droits des fichiers
modifierWindows
modifierSous Windows il suffit de se rendre dans l'onglet sécurité des propriétés d'un fichier, pour cocher les cases autorisant le programme à le lire et/ou le modifier.
Unix
modifierchmod est le système de droit d'accès a un fichier Unix. Il s'agit d'un nombre à trois chiffres que l’on attribut à un fichier (ex. : 755). Il détermine le droit d'accès au fichier en question, qui peut le modifier.
Selon sa valeur le système d'exploitation autorise ou non la modification du fichier. Sous GNU/Linux, l'utilisateur 'root', (superutilisateur), a tous les droits, c'est-à-dire qu’il peut modifier tous les fichiers.
Lorsque qu'un fichier est créé manuellement, le chmod du fichier en question est 755, avec un tel chmod nous ne pouvons pas modifier le fichier avec un script PHP. Pour pouvoir le modifier, il suffit juste de changer le chmod du fichier, en lui donnant la valeur 766. Sous Windows, cette notion est masquée et il suffit d’être administrateur de la machine (utilisateur par défaut) pour pouvoir modifier un fichier.
- Pour récupérer les permissions :
fileperms($localFilePath) & 0777
- Le propriétaire :
fileowner($localFilePath))
Ouvrir un fichier
modifierPour déclencher l'ouverture d'un fichier chez celui qui exécute le script, on précise son type puis son emplacement :
header("Content-Type: application/pdf");
header("Content-Disposition: inline; filename='".$fichier."'");
Télécharger un fichier
modifierheader("Content-Type: application/pdf");
header("Content-Disposition: attachment; filename='".$fichier."'");
Le téléchargement ne doit pas être précédé d'affichages (ex : echo
ou logs de warning) sinon ils apparaitront dans l'en-tête du fichier, le rendant illisible.
Zipper un fichier
modifierInstallation
modifierCette fonctionnalité est fournie nativement depuis PHP 5.2.0. Par contre sur les versions >= 7 sur Linux il faut l'installer :
RUN apt-get update && \ apt-get install -y \ libzip-dev \ && docker-php-ext-install zip
Utilisation
modifierPour compresser des fichiers, il faut d'abord créer l'archive vide, puis les y ajouter un par un avec la méthode addFile(Fichier source, Nom du fichier dans l'archive)
[5] :
$zip = new ZipArchive();
$f = '../Temp/'.$nomFichier . '.zip';
if ($zip->open($f, ZipArchive::CREATE) !== true) {
exit('Impossible de créer le .zip');
}
$zip->addFile('../Temp/' . $nomFichier . '.xls', $nomFichier . '.xls');
$zip->close();
Dézipper un fichier
modifier$zip = new ZipArchive();
$f = '../Temp/'.$nomFichier . '.zip';
if ($zip->open($f) === true) {
$zip->extractTo('../Temp/');
$zip->close();
}
Pour les .gz[6] :
private function uncompressFile(string $target): void
{
$uncompressedFileName = str_replace('.gz', '', $target);
$file = gzopen($target, 'rb');
$outFile = fopen($uncompressedFileName, 'wb');
while (!gzeof($file)) {
fwrite($outFile, gzread($file, 4096));
}
fclose($outFile);
gzclose($file);
Éditer et fermer un fichier
modifierCréer un fichier avec un attribut chmod de 766. Ensuite il faut ouvrir le fichier en question avant de lire/écrire. Pour cela la fonction fopen est là :
Explication : La fonction fopen à besoin de deux paramètres pour pouvoir s'exécuter :
- $nomFichier, il s'agit du chemin du fichier
- $mode, il s'agit du mode de l'ouverture
La fonction fopen utilise le premier paramètre, pour déterminer le chemin du fichier a ouvrir/créer.
Voici les différents modes d'ouvertures pour la fonction fopen :
Mode | Description |
---|---|
r | (read) 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 | (write) Ouvre en écriture seule, et 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, et 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 | (append) Ouvre en écriture seule, et place le pointeur de fichier à la fin du fichier. Si le fichier n'existe pas, on tente de le créer. |
a+ | Ouvre en lecture et écriture, et place le pointeur de fichier à la fin du fichier. Si le fichier n'existe pas, on tente de le créer. |
x | Créé et ouvre le fichier en lecture seule ; 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-jacente. Cette option est supportée à partir de PHP 4.3.2 et fonctionne uniquement avec des fichiers locaux. |
x+ | Crée et ouvre le fichier en lecture et écriture ; 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. |
c | Ouvre le fichier en écriture seule ; place le pointeur de fichier au début du fichier.
Si le fichier existe déjà, il ne le tronque pas, sinon il le crée. |
c+ | Ouvre le fichier en lecture et écriture, puis se comporte comme "c". |
Pour le fermer maintenant, il y a la fonction fclose.
Copier un fichier
modifierif (!copy($ancienFichier, $nouveauFichier)) {
echo 'La copie a échoué.';
}
Pour les images il existe aussi imagecopyresampled
[7].
Supprimer un fichier
modifierif (!unlink($fichier)) {
echo 'La suppression a échoué.';
}
Interagir avec le fichier
modifierLecture
modifierUne fois ouvert, il existe plusieurs manière de lire le contenu d'un fichier : caractère par caractère, ligne par ligne, jusqu'à une certaine taille, ou tout entier.
Tout le fichier
modifierfile
modifierPour stocker le fichier entier dans un tableau, on peut utiliser file() qui renvoie un tableau séparant chaque ligne du fichier :
Ainsi, $fichier[0] correspond à la première ligne, $fichier[1] à la seconde, etc.
Si le fichier sature la mémoire, utiliser file_lines() avec les générateurs[8].
file_get_contents
modifierPour stocker le fichier entier dans un scalaire, on utilise cette fonction.
readfile
modifierPour afficher tout le fichier dans la sortie standard[9].
Ligne par ligne
modifierfgets
modifierLa méthode générale pour lire ligne par ligne avec la fonction fgets, dont la définition est la suivante :
La variable $objetFichier doit être le résultat de l'ouverture d'un fichier avec fopen. Pour lire un fichier en entier, il suffit d’utiliser fgets en boucle ; la condition de sortie de la boucle serait alors l'arrivée à la fin de fichier, évènement notifié par la fonction feof.
Exemple de parcours d'un fichier ligne par ligne
|
<?php
$nomFichier = "chemin_ou_nom_de_fichier";
$objetFichier = fopen($nomFichier, "r"); //ouverture en lecture
if ($objetFichier) {
//on lit le fichier tant que la fin n'est pas atteinte
while (!feof($objetFichier)) {
$ligne = fgets($objetFichier);
echo $ligne;
}
fclose($objetFichier);
} else {
echo "Erreur : impossible d'ouvrir le fichier.";
}
|
fgetc
modifierLa fonction équivalente pour lire caractère par caractère se nomme fgetc :
Notez que cette fonction retourne FALSE arrivée à la fin du fichier. Lors d'un parcours, il faut donc tester impérativement la valeur avant de l’utiliser, avec un test logique de la forme « $caractere !== FALSE ».
fgetcsv
modifierCette fonction fonctionne comme "fgets" sauf qu'en plus elle utilise le séparateur "," (qui peut être changé par le paramètre "delimiter"[10]) pour créer un sous-tableau de champs par ligne.
Écriture
modifierUne fois le fichier ouvert, l'écriture se fait via la fonction fwrite.
Explication :
- $objetFichier : variable pointant vers un fichier ouvert avec fopen
- $chaine : la chaîne à écrire dans le fichier
- retour : le nombre de caractère écrits, ou FALSE si erreur
L'utilisation est alors la même que pour la lecture : ouvrir le fichier, écrire et fermer.
Exemple d'écriture
|
<?php
$nomFichier = "chemin_ou_nom_de_fichier";
$chaine = "Je suis une chaine écrite par PHP !\n"
$objetFichier = fopen($nomFichier, "w"); //ouverture en lecture
if ($objetFichier) {
if(fwrite($objetFichier, $chaine) === FALSE) {
echo "Erreur : impossible d'écrire dans le fichier.";
}
fclose($objetFichier);
} else {
echo "Erreur : impossible d'ouvrir le fichier.";
}
|
Attention : Si vous ouvrez le fichier avec l'option w ou w+, le contenu du fichier sera effacé s'il existait. Pour écrire à la fin, il faut ouvrir avec les options a ou a+ (voir ci-dessus). Enfin, si vous pouvez avec l'option r+, le contenu sera écrasé, puisque le pointeur de fichier sera placé au début.
Par ailleurs, la fonction file_put_contents() effectue un fopen(), fwrite() et fclose() successivement[11].
Se déplacer
modifierParfois, il peut être nécessaire de se déplacer dans le fichier, par exemple pour revenir au début. Pour cela, il faut utiliser la fonction fseek comme suit :
Explication :
- $objetFichier : variable pointant vers un fichier ouvert avec fopen
- $position : la position à laquelle on veut se déplacer. Pour revenir au début, $position doit valoir zéro.
Pour aller à la fin :
Fichiers uploadés
modifierCopier-coller ces lignes dans un fichier vierge upload.php pour qu’il affiche le nom des fichiers qu'on upload avec :
<?php
echo '
<form method="POST" action="upload.php" enctype="multipart/form-data">
<input type="file" name="fichier">
<input type="submit" name="envoyer" value="Uploader">
</form>';
if (isset($_FILES['fichier'])) {
echo $_FILES['fichier']['name'];
}
Il existe la fonction is_uploaded_file() pour vérifier si un fichier est bien issu d'un upload[12], et move_uploaded_file() pour le déplacer.
Fichiers temporaires
modifierPour créer des fichiers qui seront automatiquement détruits en fin de connexion, le dossier temporaire est accessible avec : sys_get_temp_dir()
.
La fonction tempnam()
quant-à elle nomme automatiquement un nouveau fichier temporaire avec un nom unique :
$fileName = tempnam(sys_get_temp_dir(), 'MonFichier1');
Fichiers distants
modifierHTTP
modifierPour lire un fichier en HTTP (par exemple cette page web) :
<?php
$page = file_get_contents("http://fr.wikibooks.org/wiki/PHP/Fichiers");
echo $page;
ou[13]
<?php
$url = 'http://fr.wikibooks.org/wiki/PHP/Fichiers';
echo htmlspecialchars(implode('', file($url)));
Pour tester si un fichier distant existe, utiliser get_headers()
[14].
FTP
modifierInstallation : dans php.ini, décommenter "extension=ftp" (anciennement "extension=php_ftp.dll").
Déposer un fichier (sans vérifier s'il en écrase un)[15] :
<?php
copy('fichier_local.txt', 'ftp://login:password@server/repertoire/fichier_distant.txt');
Souvent le répertoire porte le nom de l'utilisateur, et on écrase le fichier s'il existe :
<?php
$serveur = 'serveur1';
$login = 'utilisateur1';
$password = 'mdp1';
$fichier = 'fichier1';
copy($fichier, 'ftp://'.$login.':'.$password.'@'.$serveur.'/'.$login.'/'.$fichier, stream_context_create(array('ftp' => array('overwrite'=>True))));
Fonctions propres au FTP, pour lire un serveur distant, y télécharger et déposer des fichiers[16] :
$cnx = ftp_connect($serveur);
$loginResult = ftp_login($cnx, $login, $password);
// Liste des noms des dossiers et fichiers du dossier distant (dans le désordre)
$dossierDistant = ftp_nlist($cnx, ".");
var_dump($dossierDistant);
// Liste des éléments du dossier distant avec leurs inodes
$dossierDistant2 = ftp_rawlist($cnx, ".");
var_dump($dossierDistant2);
// Change de répertoire :
var_dump(ftp_pwd($cnx));
ftp_chdir($cnx, 'tmp');
var_dump(ftp_pwd($cnx));
// Téléchargement du dernier fichier distant
sort($dossierDistant);
$distant = $dossierDistant[sizeof($dossierDistant)-1];
$local = 'FichierLocal.txt';
if (!ftp_get($cnx, $local, $distant, FTP_BINARY)) {
echo "Erreur ftp_get\n";
} else {
ftp_delete($cnx, $distant);
}
// Téléversement d'un fichier local
$local = 'FichierLocal2.txt';
if (!ftp_put($cnx, $distant, $local, FTP_ASCII)) {
echo "Erreur ftp_put\n";
}
Pour définir le timeout, voir ftp_set_option()
[17].
SFTP
modifierOn utiliser les trois fonctions suivantes pour construire l'URL ouverte par fopen
[18] :
$connexion = ssh2_connect('tools-login.wmflabs.org', 22);
ssh2_auth_password($connexion, 'monLogin', 'MonMotDePasse');
$sftp = ssh2_sftp($connexion);
$stream = fopen("ssh2.sftp://$sftp/monFichier", 'r');
php://
modifierCe protocole donne accès aux flux (entrant et sortant) de PHP[19].
- php://fd : file descriptor.
- php://filter
- php://input : lecture de ce qui est posté.
- php://memory
- php://output : écriture.
- php://stderr
- php://stdin
- php://stdout
- php://temp
Fichiers structurés
modifierLes fichiers structurés comme les PDF, XML, DOCX et XLSX peuvent facilement être manipulés par des bibliothèques et frameworks existant, qui seront abordés dans les chapitres suivants.
Références
modifier- ↑ http://php.net/manual/fr/function.file-exists.php
- ↑ https://www.php.net/manual/en/function.filesize.php
- ↑ http://php.net/manual/fr/function.glob.php
- ↑ http://php.net/manual/fr/dir.constants.php
- ↑ http://php.net/manual/fr/ziparchive.addfile.php
- ↑ https://stackoverflow.com/questions/11265914/how-can-i-extract-or-uncompress-gzip-file-using-php
- ↑ http://php.net//manual/fr/function.imagecopyresampled.php
- ↑ https://www.startutorial.com/articles/view/php-generator-reading-file-content
- ↑ https://www.php.net/manual/en/function.readfile.php
- ↑ http://php.net/manual/fr/function.fgetcsv.php
- ↑ http://php.net/manual/fr/function.file-put-contents.php
- ↑ https://www.php.net/manual/en/function.is-uploaded-file.php
- ↑ developpez.net
- ↑ http://php.net/manual/fr/function.get-headers.php
- ↑ http://php.net/manual/fr/book.ftp.php
- ↑ http://php.net/manual/fr/function.ftp-nlist.php
- ↑ http://php.net/manual/fr/function.ftp-set-option.php
- ↑ http://php.net/manual/fr/function.ssh2-sftp.php
- ↑ http://php.net/manual/fr/wrappers.php.php