Les fonctions Zip en PHP

Formation

En Ligne

Prix sur demande

Appeler le centre

Avez-vous besoin d'un coach de formation?

Il vous aidera à comparer différents cours et à trouver la solution la plus abordable.

Description

  • Typologie

    Formation

  • Méthodologie

    En ligne

Grâce à cette formation vous pourrez acquérir les connaissances nécessaires qui vous permettrons d’ajouter des compétences à votre profil et obtenir de solides aptitude qui vous offriront de nombreuses opportunités professionnelles.

Questions / Réponses

Ajoutez votre question

Nos conseillers et autres utilisateurs pourront vous répondre

À qui souhaitez-vous addresser votre question?

Saisissez vos coordonnées pour recevoir une réponse

Nous ne publierons que votre nom et votre question

Les Avis

Le programme

Introduction du cours

Bien souvent, il arrive qu’on veuille récupérer le contenu d’un dossier ; or à moins de télécharger les fichiers un à un, ce n’est pas possible. Avec PHP on peut cependant créer une archive Zip et la proposer au téléchargement.

Les bases nécessaires à la compréhension de ce tutoriel sont la programmation en PHP ( :p ) et la programmation orientée objet (tutoriel de vyk12), car les fonctions zip_* ne sont pas nombreuses et ne permettent que la lecture et l’extraction d’une archive. On utilisera donc la classe ZipArchive.
Pour pouvoir utiliser cette classe, il faut que l’extension php_zip soit activée, si elle ne l’est pas il faut la décommenter dans le fichier php.ini.

Ce tutoriel servira d’introduction aux fonctions Zip.

Instancier la classe ZipArchive

Je ne suis pas là pour vous apprendre à faire de la POO donc je ne m’étendrai pas là-dessus ; les mots instance, classe, etc. doivent vous être familiers.
Le nom de la classe est ZipArchive (documentation), elle permet de gérer totalement une archive de type zip. Elle ne prend aucun paramètre à son instanciation.

<?php $zip = new ZipArchive(); ?>

Ceci va donc créer une instance de cette classe que l’on pourra manipuler tout au long du code.

Créer, ouvrir, fermer une archive

Le nom de mon instance de ZipArchive sera $zip durant tout le tutoriel.
On a instancié notre classe, on peut donc commencer à la manipuler. Il y a deux cas possibles pour l’ouverture d’une archive :

  • on crée une nouvelle archive ;

  • on ouvre une archive existante.

La méthode destinée à ouvrir une archive est <?php $zip->open(); ?> .
Si on veut créer une nouvelle archive, il faudra passer en argument la valeur ZipArchive::CREATE  qui lui indiquera qu’il faut ouvrir une nouvelle archive.
Si l’ouverture réussit, la méthode renvoie « TRUE », sinon elle renvoie un code d’erreur. Une liste complète des codes d’erreur est disponible ici.

Pour créer une nouvelle archive, le fichier doit avoir les droits en écriture.
En cas de problème, chmod 0777 <fichier>.

<?php $zip = new ZipArchive(); // On ouvre l’archive. if($zip->open('Zip.zip') == TRUE) // On crée l’archive. if($zip->open('Zip.zip', ZipArchive::CREATE) == TRUE) { echo '&quot;Zip.zip&quot; ouvert'; } else { echo 'Impossible d&#039;ouvrir &quot;Zip.zip&quot;'; // Traitement des erreurs avec un switch(), par exemple. } ?>

À titre informatif, j’ai pris l’habitude de convertir les entités accentuées et autres choses du même genre en code (x)HTML, c’est pour cela que des &quot; et &#039; sont présents dans le code.

Le code ci-dessus ne fera strictement rien si on crée une nouvelle archive zip car celle-ci est vide et donc ne sera pas sauvegardée. De plus, on ne ferme pas la ressource que nous renvoie $zip.

<?php $zip = new ZipArchive(); // On ouvre l’archive. if($zip->open('Zip.zip') == TRUE) // On crée l’archive. if($zip->open('Zip.zip', ZipArchive::CREATE) == TRUE) { echo '&quot;Zip.zip&quot; ouvert'; $zip->close(); } else { echo 'Impossible d&#039;ouvrir &quot;Zip.zip&quot;'; // Traitement des erreurs avec un switch(), par exemple. } ?>

On sait donc comment créer, ouvrir et fermer une archive. Nous allons maintenant passer à l’ajout de fichiers.

Ajouter, renommer, supprimer et extraire des fichiersAjouter des fichiers

On dispose donc d’une archive avec le code de la partie précédente et à laquelle on va ajouter des fichiers. Commençons avec de simples fichiers texte (*.txt).
Il existe deux méthodes pour cela :

  • addFile, pour ajouter un fichier existant ;

  • addFromString, pour écrire directement le contenu.

Ces deux méthodes sont donc <?php $zip->addFile(); ?> et <?php $zip->addFromString(); ?> (elles écrasent le contenu si le fichier existe déjà), elles renvoient toutes les deux un booléen.
Notez que <?php $zip->addFile(); ?> possède un paramètre facultatif qui permet de changer le nom du fichier dans l’archive.

bool ZipArchive::addFile ( string $filename [, string $localname ] )

Le contenu du fichier .txt sera très simple.

Je suis le contenu de Fichier.txt !<?php $zip = new ZipArchive(); if($zip->open('Zip.zip', ZipArchive::CREATE) === true) { echo '&quot;Zip.zip&quot; ouvert<br/>'; // Ajout d’un fichier. $zip->addFile('Fichier.txt'); // Ajout direct. $zip->addFromString('Fichier.txt', 'Je suis le contenu de Fichier.txt !'); // Et on referme l'archive. $zip->close(); } else { echo 'Impossible d&#039;ouvrir &quot;Zip.zip<br/>'; // Traitement des erreurs avec un switch(), par exemple. }

L’ajout de fichier est donc très simple : pour de simples fichiers contenant du texte on passe par <?php $zip->addFromString(); ?> et pour ce qui est des images, des documents Word, XML, etc., on passe par <?php $zip->addFile(); ?>.

Si on veut organiser son archive, on peut y créer des dossiers, soit en passant par <?php $zip->addEmptyDir('Le nom du dossier'); ?>, soit en précisant directement un nom de dossier lors de l’ajout du fichier.

<?php $zip = new ZipArchive(); if($zip->open('Zip.zip', ZipArchive::CREATE) === true) { echo '&quot;Zip.zip&quot; ouvert<br/>'; // Création d'un dossier par addEmptyDir(). [Facultatif] $zip->addEmptyDir('Fichiers textes'); // Ajout d'un fichier. $zip->addFile('Fichiers textes/Fichier.txt'); // Ajout directement. $zip->addFromString('Fichiers textes/Fichier.txt', 'Je suis le contenu de Fichier.txt !'); // Et on referme l’archive. $zip->close(); } else { echo 'Impossible d&#039;ouvrir &quot;Zip.zip<br/>'; // Traitement des erreurs avec un switch(), par exemple. } Renommer et supprimer

Pour renommer et supprimer des fichiers, on dispose de deux méthodes. On peut soit passer le nom du fichier, soit passer son numéro d'index (récupérable par <?php $zip->locateName('nom du fichier'); ?>). Elles renvoient toutes deux un booléen indiquant le succès de l’opération.

<?php // Suppression en passant par l’index. $zip->deleteIndex(3); // Suppression en passant par le nom du fichier. $zip->deleteName('Nom du fichier.extension'); // Renommer en passant par l’index. $zip->renameIndex(3, 'Nouveau nom.extension'); // Renommer en passant par le nom. $zip->renameName('Fichier.extension', 'Nouveau Nom.extension'); ?> Extraire les fichiers

Il est possible d’extraire le contenu de l’archive (seulement une/plusieurs entrée(s) ou même l’archive complète) grâce à la méthode <?php $zip->extractTo(); ?>.

<?php // Extraction unique dans le dossier courant. $zip->extractTo('.', 'Fichier.txt'); // Extractions multiples dans le dossier courant. $zip->extractTo('.', array('Fichier.txt', 'Autre fichier.txt')); ?> Autres opérations

La classe ZipArchive possède d’autres méthodes qui permettent de gérer les commentaires sur l’archive et ses fichiers, d’annuler les actions faites depuis l'ouverture, de récupérer les statistiques d’un fichier, etc.

<?php // Mettre un commentaire sur l’archive. $zip->setArchiveComment('Mon joli commentaire sur l\'archive.'); // Récupérer le commentaire sur l’archive. $commentaire = $zip->getArchiveComment(); // Mettre un commentaire sur un fichier. $zip->setCommentIndex(3, 'Mon joli commentaire de fichier.'); $zip->setCommentName('Fichier.extension', 'Et paf un commentaire !'); // Récupérer le commentaire sur le fichier. $commentaire = $zip->getCommentIndex(3); $commentaire = $zip->getCommentName('Fichier.extension'); ?>

S’il y a un nombre conséquent d’archives *.zip, on peut se servir des commentaires pour préciser leur contenu lorsque celui-ci n’est pas explicité par le nom (il en va de même pour les fichiers si leurs noms ne sont également pas significatifs).

Pour ce qui est de l’annulation de modifications, je vous laisse lire la documentation :

  • ZipArchive::unchangeAll() ;

  • ZipArchive::unchangeArchive() ;

  • ZipArchive::unchangeIndex() ;

  • ZipArchive::unchangeName().

Pour récupérer le contenu d’un fichier présent dans l’archive, on peut récupérer un flux (resource) de la même manière qu’avec fopen() qu’on pourra ensuite exploiter uniquement au moyen de fonctions de lecture comme fgetc(), fgets(), fread(), etc., étant donné que l’écriture n’est pas encore implémentée.
On peut s’en servir pour vérifier le contenu d'un fichier (grâce aux sommes md5 ou sha1, par exemple), récupérer un fichier sans extraire toute l’archive, etc.

<?php $flux = $zip->getStream('Fichier.extension'); // Je ne teste pas si le flux est bien retourné mais normalement il faut le tester, avec is_resource(), par exemple. $temp = ''; while($ligne = fgets($flux)) { $temp .= $ligne; } echo $temp; ?>

Ci-dessous, un exemple de récupération directe de contenu sans passer par une fonction f*().

<?php // Récupérer le contenu d’un fichier directement avec l'index du fichier ou son nom. $contenu = $zip->getFromIndex(3); $contenu = $zip->getFromName('Fichier.extension'); ?>

L’inverse de ZipArchive::locateName() est ZipArchive::getNameIndex(), qui permet d’obtenir le nom d’un fichier à partir de son index.

Il existe bien d’autres fonctions qui sont toutes consultables ici.

T.P. — Récupérer une archive d’un dossierSujet

Rien ne vaut un bon T.P. pour finir ce tutoriel assez simple. Pour ceux qui connaissent Dotclear, bien que cela doit exister ailleurs aussi, vous avez pu remarquer la possibilité de « Télécharger ce répertoire dans un fichier zip ». L’objectif de ce T.P. est donc le suivant : récupérer le contenu d’un dossier dans une archive et la proposer en téléchargement.
Je vous renvoie à cette sous-partie du tuto de DHKold. Lisez le passage expliquant comment envoyer un fichier au client dans « Téléchargement avec compteur ».
Voici quelques méthodes pour lister les fichiers dans un dossier :

  • scandir() ;

  • glob() ;

  • opendir() couplé avec readdir().

Vous pouvez ensuite décider d’implémenter ou non la récursivité. Si oui, un dossier présent dans le répertoire à archiver sera lui aussi mis dans le fichier zip. Sinon, il ne sera pas pris en compte et seuls les fichiers se trouvant directement dans le répertoire courant seront pris en compte.

Après, tout dépend de vous, le corrigé vous présentera une méthode sans la récursivité, pour faciliter les choses.

Attention ! 3, 2, 1, Codez ! Oui, je m’y crois trop. :p

Solution

Ma solution n’est pas la solution, c’est simplement une solution possible.

<?php // On instancie la classe. $zip = new ZipArchive(); if(is_dir('upload/')) { // On teste si le dossier existe, car sans ça le script risque de provoquer des erreurs. if($zip->open('Archive.zip', ZipArchive::CREATE) == TRUE) { // Ouverture de l’archive réussie. // Récupération des fichiers. $fichiers = scandir('upload/'); // On enlève . et .. qui représentent le dossier courant et le dossier parent. unset($fichiers[0], $fichiers[1]); foreach($fichiers as $f) { // On ajoute chaque fichier à l’archive en spécifiant l’argument optionnel. // Pour ne pas créer de dossier dans l’archive. if(!$zip->addFile('upload/'.$f, $f)) { echo 'Impossible d&#039;ajouter &quot;'.$f.'&quot;.<br/>'; } } // On ferme l’archive. $zip->close(); // On peut ensuite, comme dans le tuto de DHKold, proposer le téléchargement. header('Content-Transfer-Encoding: binary'); //Transfert en binaire (fichier). header('Content-Disposition: attachment; filename="Archive.zip"'); //Nom du fichier. header('Content-Length: '.filesize('Archive.zip')); //Taille du fichier. readfile('Archive.zip'); } else { // Erreur lors de l’ouverture. // On peut ajouter du code ici pour gérer les différentes erreurs. echo 'Erreur, impossible de créer l&#039;archive.'; } } else { // Possibilité de créer le dossier avec mkdir(). echo 'Le dossier &quot;upload/&quot; n&#039;existe pas.'; } ?>

Voilà, ce tutoriel est fini.
J’espère vous avoir aidés. Si vous avez une question vous pouvez me contacter par M.P. :)

  • #
Waouh !

Très heureux de voir que nos cours vous plaisent, déjà 3 pages lues aujourd'hui ! Vous pouvez continuer la lecture de nos cours en devenant un Roomie, un membre de la communauté d'OpenClassrooms. C'est gratuit !

Vous pourrez aussi suivre votre avancement dans le cours, faire les exercices et discuter avec les autres Roomies.

S'inscrire Se connecter
  • Thématiques du cours : PHP Web

Chaque cours est créé par un professeur ou un expert dans le domaine. Il est composé d'une ou plusieurs parties et peut comporter du texte, des images (schéma, illustration) et des vidéos. Chaque partie d'un...

Appeler le centre

Avez-vous besoin d'un coach de formation?

Il vous aidera à comparer différents cours et à trouver la solution la plus abordable.

Les fonctions Zip en PHP

Prix sur demande