En PHP, le processus général est le suivant:
$zip = zip_open("example.zip");
if (is_resource($zip)) {
while ($entry = zip_read($zip)) {
echo "Name: " . zip_entry_name($entry) . "\n";
if (zip_entry_open($zip, $entry, "r")) {
$contents = zip_entry_read($entry, 1024);
echo "Content: " . $contents . "\n";
zip_entry_close($entry);
}
}
zip_close($zip);
}
Le code ci-dessus est une utilisation typique donnée par la documentation officielle PHP. Il fonctionne bien dans de nombreux scénarios, mais tant qu'il est un peu plus compliqué, ou que le contenu lit dépasse une certaine taille, le problème se pose.
Le contenu ne peut pas être lu : zip_entry_read () renvoie une chaîne vide.
Certains fichiers sont interrompus à mi-chemin par la lecture : seul le contenu partiel peut être lu.
Signaler une erreur ou coincée : certains packages compressés entraîneront la collaboration de l'exécution de PHP.
L'ordre de lecture est déroutant : le contenu d'une entrée multiple est entrelacé ensemble.
Ces problèmes ont une chose en commun: les problèmes disparaissent généralement tant que vous passez à d'autres bibliothèques, comme Ziparchive. Cela montre que le problème n'est probablement pas dans le fichier ZIP lui-même, mais dans le mécanisme d'utilisation ou de mise en œuvre de la fonction ZIP_ * .
zip_read () est essentiellement un itérateur qui maintient en interne le pointeur de lecture du zip à chaque fois qu'il est appelé. Si vous appelez le prochain zip_read () pendant le processus de lecture (par exemple, avant d'avoir fini de lire une entrée), l'état de lecture de l'entrée précédente sera détruit.
zip_entry_read () ne garantit pas que toutes les données seront lues en même temps, surtout lorsque vous passez une longueur fixe (telle que 1024), vous devez passer à travers pour lire jusqu'à ce que la chaîne vide soit retournée, sinon le contenu sera perdu.
C'est également le cœur de cet article: zip_entry_read () dépend essentiellement de l'état d'entrée actuellement maintenu par zip_read () . Si vous appelez à nouveau zip_read () lorsque vous appelez zip_entry_read () (même dans une autre branche logique), l'ancien comportement sera interrompu.
Ne saisissez pas le prochain zip_read () lorsque le contenu de l'entrée actuel n'a pas été lu, sinon le pointeur de lecture sera déplacé à l'avance, entraînant un contenu perdu ou incorrect.
while ($entry = zip_read($zip)) {
zip_entry_open($zip, $entry, "r");
$content = "";
while ($data = zip_entry_read($entry, 1024)) {
$content .= $data;
}
echo $content;
zip_entry_close($entry);
}
Certains fichiers zip peuvent être compressés par des outils non standard et peuvent contenir des structures irrégulières. Il est recommandé d'utiliser la classe Ziparchive pour coopérer avec la méthode Isreadable () pour vérifier d'abord l'intégrité.
$zip = new ZipArchive();
if ($zip->open('example.zip') === TRUE) {
// Logique de vérification
$zip->close();
}
Bien que des fonctions telles que zip_open () soient concises et faciles à utiliser, elles ont été marquées comme expérimentales (ou même pas recommandées) dès le début, tandis que la classe ziparchive est plus puissante et stable, et peut mieux faire face à des fichiers zip complexes.
$zip = new ZipArchive();
if ($zip->open('example.zip') === TRUE) {
for ($i = 0; $i < $zip->numFiles; $i++) {
$entryName = $zip->getNameIndex($i);
echo "File: " . $entryName . "\n";
$stream = $zip->getStream($entryName);
if ($stream) {
while (!feof($stream)) {
echo fread($stream, 1024);
}
fclose($stream);
}
}
$zip->close();
}
Cette méthode est non seulement plus efficace, mais n'a pas non plus le problème de l'interruption de lecture zip_entry_read () , et est plus adapté à une utilisation dans les environnements de production.
La raison pour laquelle zip_read () et zip_entry_read () se produisent fréquemment lorsqu'ils sont utilisés ensemble est qu'ils ont une forte dépendance à l'état du pointeur interne. Une fois que vous ne faites pas attention à l'ordre de traitement et au rythme de lecture, vous êtes sujet aux troubles logiques. Il est recommandé que les projets avec des exigences de stabilité élevées pour les opérations ZIP soient prioritaires à l'utilisation de Ziparchive au lieu de cet ensemble de fonctions sous-jacentes.
Si vous devez utiliser la famille de fonctions zip_ * , assurez-vous toujours que l'ordre de lecture est rigoureux, lisez le contenu de chaque entrée intacte et évitez d'entrer dans la prochaine série de lecture sans fermer l'entrée.
Document de référence: https://www.php.net/manual/zh/ref.zip.php