PHP 4 et 5 : l'extension ZIP
Date de publication : 28/04/2007
Par
julp (Autres articles)
Le format ZIP fait indéniablement partie des standards en matière de
compression. Il mérite donc que nous nous y attardions au travers d'un
article d'autant plus que son support varie d'une version de PHP à une
autre.
1. PHP4
1.1. Installation
1.1.1. Windows
1.1.2. Linux
1.1.2.1. Statique
1.1.2.2. Dynamique
1.2. Utilisation
1.2.1. Lister le contenu d'une archive
1.2.2. Extraire une archive
2. PHP5
2.1. Installation
2.1.1. Windows
2.1.2. Linux/Unix
2.1.2.1. Statique
2.1.2.2. Dynamique
2.2. Aperçu de la classe ZipArchive
2.3. Utilisation de la classe ZipArchive
2.3.1. Créer une archive
2.3.2. Ajouter/Modifier un fichier à une archive
2.3.3. Supprimer un fichier d'une archive
2.3.4. Lister une archive
2.3.5. Obtenir des informations sur un fichier particulier de l'archive
2.3.6. Extraire une archive
2.4. Lecture d'une archive comme d'un flux
3. Conclusion
3.1. Epilogue
3.2. Remerciements
1. PHP4
L'extension Zip pour ces versions de PHP est limitée à l'accès en lecture
sur l'archive. Vous ne pouvez en outre que lire le contenu d'une archive
et obtenir diverses informations sur les fichiers contenus dans celle-ci
ou encore les extraire mais en aucun cas en créer ou modifier une.
1.1. Installation
1.1.1. Windows
Récupérez la
version binaire de PHP pour Windows ou uniquement cette
extension précise sur le site
PECL4WIN.
Placez la avec les autres (répertoire souvent nommé
extensions) puis chargez l'extension dans le fichier
php.ini à l'aide de la ligne suivante :
Un redémarrage de votre serveur Apache sera requis afin de
prendre en charge immédiatement cette nouvelle extension.
1.1.2. Linux
Réservez l'installation de PHP à partir de ses sources à des
besoins particuliers surtout si vous êtes débutants dans ce
domaine, privilégiez dans la mesure du possible les paquetages
binaires officiels mis à votre disposition par le distributeur
de votre système Linux auquel cas il ne devrait vous rester qu'à
charger la nouvelle extension en éditant le fichier php.ini
(référez vous à la partie intitulée Dynamique ci-dessous pour cela).
Sur une distribution Mandriva avec des médias correctement
renseignés, la commande urpmi php4-zip suffira.
La librairie
ZZIPlib
(et ses fichiers d'en-tête), version minimale 0.10.6, vous sera
requise.
1.1.2.1. Statique
L'extension ZIP étant intégrée aux sources de PHP, il nous
suffit de manifester notre intérêt en ajoutant l'option
--with-zip au script de configuration :
./configure --prefix=/usr/local/php4 ... --with-zip
make
make install
|
1.1.2.2. Dynamique
Le recours à une compilation dynamique peut se faire après
la compilation du coeur de PHP vous évitant de repasser par
une recompilation complète de PHP mais permet également de
mettre à jour l'un ou l'autre de façon plus ou moins
indépendante. Les commandes à saisir sont alors les
suivantes :
cd /répertoire/des/sources/de/l/extension
phpize
./configure
make
make install
|
Il est nécessaire d'indiquer à PHP de charger l'extension ZIP
en éditant le fichier php.ini pour y ajouter la ligne
suivante :
La directive extension_dir du même fichier doit être
correcte sous peine d'erreurs car PHP sera alors incapable de
trouver la librairie. Si PHP se présente en tant que module
du serveur web, il vous sera nécessaire de redémarrer ce
dernier afin de disposer du support de l'extension ZIP.
1.2. Utilisation
1.2.1. Lister le contenu d'une archive
Obtenir la liste des entrées d'une archive ZIP se résume dans un
premier temps à l'ouvrir puis à en parcourir les entrées et pour
terminer à la fermer.
L'ouverture se fait à l'aide de la fonction zip_open qui n'a pour
seul paramètre le nom de l'archive et qui vous renverra FALSE en
cas d'erreur ou alors une ressource qui vous permettra de
l'explorer par la suite.
Le parcours des entrées de l'archive se fait une à une par le
biais de la fonction zip_read, qui fournit pour chaque entrée
une ressource décrivant celle-ci ou FALSE si la fin de l'archive
a été atteinte. Il est possible d'exploiter cette ressource afin
d'obtenir diverses informations sur le fichier compressé à raison
d'une fonction par critère :
- zip_entry_name() : le nom du fichier
- zip_entry_compressedsize() : la taille du fichier après compression
- zip_entry_compressionmethod() : la méthode de compression utilisée
- zip_entry_filesize() : taille non compressée du fichier
N'omettons pas après cela de refermer l'archive avec la fonction
zip_close.
Puisqu'un exemple vaut toujours mieux qu'un long discours :
<style type="text/css">
table.zip_details {
border: 3px double black;
border-collapse: collapse;
}
table.zip_details td,
table.zip_details th {
border: 1px solid black;
}
table.zip_fichiers td,
table.zip_fichiers th {
border: 0px none;
}
-->
</style>
<?php
function formater_taille($taille) {
$unites = array('o', 'ko', 'Mo', 'Go');
for ($u = count($unites); $u >= 0; $u--) {
if (isset($unites[$u]) && $taille >= 1024 * pow(1024, $u - 1)) {
$taille = $taille / pow(1024, $u);
$unite = $unites[$u];
break;
}
}
if ($u > 0) {
return number_format($taille, 2, ',', ' ') . ' ' . $unite;
} else {
return $taille . ' ' . $unite;
}
}
function afficher_zip($archive) {
if (($zip = zip_open($archive)) === FALSE) {
return FALSE;
}
echo '<table class="zip_details">';
echo '<tr><th colspan="2">' . $archive . '</th></tr>';
echo '<tr><td>Taille :</td><td>' . formater_taille(filesize('sources.zip')) . '</td></tr>';
$nbEntrees = 0;
echo '<tr>
<td>Fichiers archivés :</td>
<td><table class="zip_fichiers">
<tr>
<th>Nom</th>
<th>Taille compressée</th>
<th>Taille non compressée</th>
</tr>';
while ($entree = zip_read($zip)) {
echo '<tr>
<td>' . zip_entry_name($entree) . '</td>
<td align="center">' . formater_taille(zip_entry_compressedsize($entree)) . '</td>
<td align="center">' . formater_taille(zip_entry_filesize($entree)) . '</td>
</tr>';
$nbEntrees++;
}
echo '</table></td></tr>';
echo '<tr><td>Nombre de fichiers archivés :</td><td>' . $nbEntrees . '</td></tr>';
echo '</table>';
zip_close($zip);
return TRUE;
}
afficher_zip('sources.zip');
?>
|
C'est la fonction afficher_zip qu'il faut regarder et comprendre.
Le restant, la CSS et la fonction formater_taille, ne sont que
secondaires et permettent d'améliorer quelque peu l'affichage
généré par afficher_zip().
1.2.2. Extraire une archive
Cette opération implique peu de changements et de nouvelles
fonctions par rapport au listing d'une archive. En effet,
l'archive est parcourue de la même manière et les seules
nouvelles fonctions que nous allons découvrir ont pour but
d'accéder au contenu d'une entrée et de la lire :
- zip_entry_open(zip, entrée) : ouvrir en lecture le fichier correspondant à la ressource entrée (obtenue par la fonction zip_read) de l'archive représentée par la ressource zip (résultat de la fonction zip_open)
- zip_entry_read(entrée, longueur) : lire le contenu de l'entrée (ressource retournée par zip_read) à hauteur de longueur octets (valeur par défaut 1024).
- zip_entry_close(entrée) : libère les ressources pour la lecture du fichier correspondant à la ressource entrée
Ces fonctions bien que portant des noms différents, se
rapprochent fortement de fopen, fread couplée à filesize (afin
de récupérer le contenu du fichier en une fois) et fclose.
function mkdir_recursif($dir) {
$parties = preg_split('#/|' . preg_quote(DIRECTORY_SEPARATOR) . '#', $dir, -1, PREG_SPLIT_NO_EMPTY);
$base = '';
foreach ($parties as $p) {
if (!file_exists($base . $p)) {
mkdir($base . $p);
}
$base .= $p . DIRECTORY_SEPARATOR;
}
}
function extractTo($archive, $destination, $ecrase = FALSE, $fichiers = NULL) {
if (($zip = zip_open($archive)) === FALSE) {
die(var_dump($zip));
return FALSE;
}
if (!file_exists($destination)) {
mkdir_recursif($destination);
}
while ($entree = zip_read($zip)) {
$fichier = zip_entry_name($entree);
if (is_array($fichiers) && !in_array($fichier, $fichiers)) {
continue;
}
if (zip_entry_open($zip, $entree)) {
$contenu = zip_entry_read($entree, zip_entry_filesize($entree));
zip_entry_close($entree);
if ($ecrase || !file_exists($destination . DIRECTORY_SEPARATOR . $fichier)) {
if (strpos($fichier, '/') !== FALSE) {
mkdir_recursif($destination . DIRECTORY_SEPARATOR . dirname($fichier));
}
$fp = fopen($destination . DIRECTORY_SEPARATOR . $fichier, 'w');
fwrite($fp, $contenu);
fclose($fp);
}
} else {
zip_close($zip);
return FALSE;
}
}
zip_close($zip);
return TRUE;
}
extractTo('sources.zip', '/home/julp/www/zip');
extractTo('mon_archive.zip', '/home/julp', TRUE, array('fichier1', 'fichier2'));
|
2. PHP5
2.1. Installation
2.1.1. Windows
Téléchargez la
version binaire pour Windows ou allez sur la page
PECL4WIN,
puis placez cette extension avec les autres (répertoire
ext en général) et enfin activez l'extension dans le
fichier php.ini :
Redémarrez finalement votre serveur Apache pour à présent
profiter du support de l'extension ZIP.
2.1.2. Linux/Unix
L'étape de compilation ne concerne uniquement une installation de
PHP à partir de ses sources qui s'adresse aux initiés pour
répondre à des besoins particuliers (application de patchs par
exemple). Dans les autres cas, il est recommandé d'employer les
paquetages fournis par votre système ou distribution auquel cas
vous devriez simplement avoir besoin d'activer l'extension via
votre fichier php.ini (voir ci-dessous dans la partie "Dynamique").
Par exemple l'installation sur la distribution Mandriva se fait
avec la commande urpmi php5-zip si vos médias sont
convenablement configurés.
Vous devez disposer de la librairie zlib (librairies et fichiers
d'en-têtes) avant d'aller plus loin.
2.1.2.1. Statique
Ceux qui utilisent une version antérieure à 5.2.0 doivent, au
préalable, effectuer quelques opérations supplémentaires car
l'extension Zip n'était pas fournie avec PHP :
-
Télécharger les sources de cette extension sur le
site
PECL.
-
Les extraire dans le répertoire ext des sources de
PHP :
tar xzf zip-<version> -C /usr/local/src/php-5.X.Y/ext
ln -s /usr/local/src/php-5.X.Y/ext/zip-<version> /usr/local/src/php-5.X.Y/ext/zip
|
-
Les intégrer pour la compilation :
cd /usr/local/src/php-5.X.Y
./buildconf --force
|
Démarrez la compilation en ajoutant l'option --enable-zip
lors de la configuration :
./configure --prefix=/usr/local/php5 ... --enable-zip
make
make install
|
2.1.2.2. Dynamique
L'avantage de cette méthode c'est que vous n'avez pas besoin
de recompiler PHP. Vous compilez en effet, sous forme
dynamique, donc autonome, l'extension Zip. Nous aurons besoin
des sources de celle-ci si elles ne sont pas déjà inclues à
PHP. Si tel n'est pas le cas, je vous invite à les
télécharger du site
PECL
puis à les décompresser. Vous voilà prêts à les compiler :
cd /répertoire/des/sources/de/l/extension
phpize
./configure
make
make install
|
Pour terminer, il faut indiquer à PHP de charger cette
extension, c'est pourquoi nous rajouterons la ligne suivante
à notre fichier de configuration php.ini :
Profitez-en pour vérifier que les chemins vers ces extensions
sont correctement renseignés à la directive extension_dir.
Redémarrez Apache pour prendre cette nouvelle extension en
compte.
2.2. Aperçu de la classe ZipArchive
En PHP 5, la manipulation d'archives est déléguée à une classe nommée
ZipArchive dont vous trouverez ci-dessous sa structure documentée :
class ZipArchive
{
const CREATE;
const EXCL;
const CHECKCONS;
const OVERWRITE;
const FL_NOCASE;
const FL_NODIR;
const FL_COMPRESSED;
const FL_UNCHANGED;
const CM_DEFAULT;
const CM_STORE;
const CM_SHRINK;
const CM_REDUCE_1;
const CM_REDUCE_2;
const CM_REDUCE_3;
const CM_REDUCE_4;
const CM_IMPLODE;
const CM_DEFLATE;
const CM_DEFLATE64;
const CM_PKWARE_IMPLODE;
const CM_BZIP2;
const ER_OK;
const ER_MULTIDISK;
const ER_RENAME;
const ER_CLOSE;
const ER_SEEK;
const ER_READ;
const ER_WRITE;
const ER_CRC;
const ER_ZIPCLOSED;
const ER_NOENT;
const ER_EXISTS;
const ER_OPEN;
const ER_TMPOPEN;
const ER_ZLIB;
const ER_MEMORY;
const ER_CHANGED;
const ER_COMPNOTSUPP;
const ER_EOF;
const ER_INVAL;
const ER_NOZIP;
const ER_INTERNAL;
const ER_INCONS;
const ER_REMOVE;
const ER_DELETED;
public $status;
public $statusSys;
public $numFiles;
public $filename;
public $comment;
@param
@param
@returnTRUE
public function open(chaîne fichier [, entier drapeaux]);
@returnTRUEFALSE
public function close();
@param
@returnFALSETRUE
public function addEmptyDir(chaîne répertoire);
@param
@param
@returnFALSETRUE
public function addFromString(chaîne nom_local, chaîne contenu);
@param
@param
@param
@param
@returnFALSETRUE
public function addFile(chaîne fichier [, chaîne nom_local [, entier début [, entier longueur]]]);
@param
|