Position actuelle: Accueil> Derniers articles> Comment traiter efficacement les packages compressés Zip contenant des répertoires imbriqués multicouches à l'aide de la fonction zip_read ()?

Comment traiter efficacement les packages compressés Zip contenant des répertoires imbriqués multicouches à l'aide de la fonction zip_read ()?

M66 2025-06-15

Travailler avec des fichiers ZIP dans PHP est une tâche courante, surtout lorsque nous devons extraire du contenu ou lire des structures de fichiers à partir d'un package compressé. La fonction zip_read () est une autre façon de traiter les fichiers ZIP en dehors de la classe Ziparchive. Il est souvent utilisé avec des fonctions telles que zip_open () et zip_entry_read () . Bien que ces fonctions soient de bas niveau, elles sont toujours d'une grande importance pour les développeurs qui souhaitent obtenir une compréhension plus profonde de la structure des fichiers zip, en particulier lorsqu'ils traitent des fichiers zip contenant des répertoires imbriqués multicouches.

Méthode d'utilisation de base

Tout d'abord, nous devons ouvrir le fichier zip avec zip_open () et parcourir chaque entrée à l'aide de zip_read () . Ce qui suit est la structure de base:

 $zip = zip_open("nested_directories.zip");

if (is_resource($zip)) {
    while ($entry = zip_read($zip)) {
        $entryName = zip_entry_name($entry);
        echo "Entry: $entryName\n";
    }
    zip_close($zip);
}

Cet extrait de code est en mesure d'énumérer toutes les entrées (y compris les répertoires et les fichiers) dans un fichier zip, mais la liste ne suffit pas, nous devons traiter plus profondément avec les structures imbriquées.

Identifier les structures de répertoire imbriquées

Les répertoires imbriqués dans les fichiers zip n'ont pas de structure "semblable à une arborescence" comme des systèmes de fichiers réels. Chaque répertoire ou fichier est exprimé en tant que chaîne de chemin, par exemple:

 photos/
photos/vacation/
photos/vacation/beach.jpg
documents/report.docx

Par conséquent, nous devons juger la profondeur du chemin du fichier en fonction de / . Chaque couche peut être analysée par simple exploit () :

 $depth = substr_count($entryName, '/');

Ceci est très utile lorsque nous devons effectuer des opérations spécifiques en fonction du niveau du répertoire.

Extraire les fichiers et conserver la structure du répertoire

Pour extraire le contenu du fichier ZIP dans un répertoire spécifié et préserver sa structure de répertoire, nous pouvons le faire en combinaison avec zip_entry_read () et file_put_contents () . Comme indiqué ci-dessous:

 $zip = zip_open("nested_directories.zip");

$extractPath = "extracted/";

if (is_resource($zip)) {
    while ($entry = zip_read($zip)) {
        if (zip_entry_open($zip, $entry, "r")) {
            $entryName = zip_entry_name($entry);
            $fullPath = $extractPath . $entryName;

            // Si c'est un répertoire,Assurez-vous de créer
            if (substr($entryName, -1) === '/') {
                if (!is_dir($fullPath)) {
                    mkdir($fullPath, 0755, true);
                }
            } else {
                // Si c'est un fichier,Assurez-vous que le répertoire précédent existe
                $dir = dirname($fullPath);
                if (!is_dir($dir)) {
                    mkdir($dir, 0755, true);
                }

                $content = zip_entry_read($entry, zip_entry_filesize($entry));
                file_put_contents($fullPath, $content);
            }

            zip_entry_close($entry);
        }
    }
    zip_close($zip);
}

Le code ci-dessus implémente la fonction d'extraction de structure imbriquée complète, gère la création de répertoires et l'écriture de fichiers, et garantit que la structure d'origine reste inchangée.

Exemples d'application pratiques

Imaginez que vous avez développé un site Web (comme https://m66.net/upload ) pour fournir une fonction de téléchargement ZIP. Le fichier zip téléchargé par les utilisateurs peut contenir des répertoires imbriqués multicouches complexes. Afin de décompresser ces fichiers en toute sécurité dans un répertoire temporaire pour un traitement ultérieur, vous pouvez d'abord extraire le contenu avec le code ci-dessus, puis traverser le dossier cible pour le traitement.

Pour éviter les vulnérabilités de traversée de trajet (comme la fermeture éclair malveillante, y compris ../../etc/passwd ), vous devez également effectuer une vérification de la sécurité après les coutures de chemin:

 $realBase = realpath($extractPath);
$realUserPath = realpath($fullPath);

if (strpos($realUserPath, $realBase) !== 0) {
    // Chemin illégal,franchir
    continue;
}

Suggestions d'optimisation des performances

  1. Évitez la lecture de fichiers inutile : Traitez uniquement les répertoires ou les fichiers requis avec des extensions spécifiques.

  2. Chargement à la demande : pour les fichiers volumineux, n'utilisez pas zip_entry_read ($ entrée, zip_entry_filesize ($ entrée)) pour charger en même temps, mais utilisez la lecture en streaming.

  3. Fonctionnement par lots : Si l'opération finale implique une base de données ou un service externe, envisagez le résultat tampon et soumettez par lots.

Résumer

Bien que l'utilisation de la fonction zip_read () pour traiter les fichiers ZIP ne soit pas aussi intuitive que Ziparchive , il est toujours très pratique dans certains scénarios où les exigences de contrôle structurel sont élevées. En analysant la chaîne de chemin, nous pouvons traiter efficacement les répertoires imbriqués multicouches et extraire en toute sécurité le contenu sur le chemin spécifié par le serveur. En combinant des mesures appropriées de sécurité et d'optimisation des performances, cette approche reste un outil puissant pour créer une logique de traitement de fichiers zip complexe.