Décompressez un fichier avec php

199

Je veux décompresser un fichier et cela fonctionne bien

system('unzip File.zip');

Mais j'ai besoin de passer le nom du fichier via l'URL et je ne peux pas le faire fonctionner, c'est ce que j'ai.

$master = $_GET["master"];
system('unzip $master.zip'); 

Qu'est-ce que je rate? Je sais que ce doit être quelque chose de petit et de stupide que je néglige.

Merci,

BostonBB
la source
35
Les guillemets doubles évaluent les variables; les guillemets simples ne le font pas. MAIS - soyez prudent, car le simple fait de transmettre une entrée à un appel système peut être très dangereux.
Wiseguy
25
Je dois dire que je n'aime pas le ton hostile de certains commentaires. Si vous vous rendez compte qu'il lui manque quelque chose, alors dites-le lui. Nous manquons tous quelque chose à un moment donné.
Sebastian Mach
L'erreur ici est simple. Vous essayez d'utiliser l'interpolation de chaînes avec des guillemets simples au lieu de guillemets doubles. L'interpolation de chaînes ne fonctionne pas avec des guillemets simples car elle est utilisée pour les littéraux de chaînes. Donc, changer votre code system("unzip $master.zip");devrait fonctionner.
Asier Paz

Réponses:

500

Je peux seulement supposer que votre code provient d'un tutoriel quelque part en ligne? Dans ce cas, bon travail en essayant de le découvrir par vous-même. D'un autre côté, le fait que ce code puisse être publié en ligne quelque part comme la bonne façon de décompresser un fichier est un peu effrayant.

PHP a des extensions intégrées pour gérer les fichiers compressés. Il ne devrait pas être nécessaire d'utiliser des systemappels pour cela. ZipArchivedocs est une option.

$zip = new ZipArchive;
$res = $zip->open('file.zip');
if ($res === TRUE) {
  $zip->extractTo('/myzips/extract_path/');
  $zip->close();
  echo 'woot!';
} else {
  echo 'doh!';
}

En outre, comme d'autres l'ont commenté, $HTTP_GET_VARSest obsolète depuis la version 4.1 ... qui était il y a très longtemps. Ne l'utilisez pas. Utilisez $_GETplutôt le superglobal.

Enfin, faites très attention à accepter toute entrée transmise à un script via une $_GETvariable.

TOUJOURS ASSAINIR L'ENTRÉE UTILISATEUR.


METTRE À JOUR

Selon votre commentaire, la meilleure façon d'extraire le fichier zip dans le même répertoire dans lequel il réside est de déterminer le chemin d'accès dur au fichier et de l'extraire spécifiquement à cet emplacement. Donc, vous pourriez faire:

// assuming file.zip is in the same directory as the executing script.
$file = 'file.zip';

// get the absolute path to $file
$path = pathinfo(realpath($file), PATHINFO_DIRNAME);

$zip = new ZipArchive;
$res = $zip->open($file);
if ($res === TRUE) {
  // extract it to the path we determined above
  $zip->extractTo($path);
  $zip->close();
  echo "WOOT! $file extracted to $path";
} else {
  echo "Doh! I couldn't open $file";
}
rdlowrey
la source
Merci pour le conseil. Je suis nouveau dans ce domaine et je viens de tout comprendre. Avec votre code, comment puis-je le décompresser dans le même dossier que le fichier compressé?
BostonBB
2
Eh bien, il existe une différence entre le répertoire de travail actuel de votre script et le répertoire où réside le fichier zip. Si le fichier zip se trouve dans le même répertoire que le script que vous pourriez faire $zip->extractTo('./');Cependant, ce n'est probablement pas le cas. Une meilleure option consiste à déterminer l'emplacement du fichier zip dans le système de fichiers et à l'extraire à cet endroit. Je mettrai à jour ma réponse pour le démontrer.
rdlowrey
Et si vous n'avez pas la classe ZipArchive disponible? Je travaille sur un site avec un hébergement de merde et je reçois l' Fatal error: Class 'ZipArchive' not founderreur que j'essaie ce script :-( Y a-t-il une option à ce stade?
CWSpear
2
@CWSpear, vous allez avoir besoin de lazlib bibliothèque sous-jacente pour effectuer à peu près toutes les opérations de compression / décompression avec PHP. Même pour effectuer des appels système, vous devez disposer de la bibliothèque sous-jacente. C'est une chose très omniprésente cependant, et ne pas l'avoir est l'exception. Si vous êtes sur l'hébergement mutualisé, ils devraient l'installer pour vous. Sinon, google juste quelque chose comme "Comment installer le support des fonctions Zip pour PHP"
rdlowrey
Ouais, c'est un hébergement assez bon marché comme on me l'a dit. Quoi qu'il en soit, merci pour la réponse, c'est une bonne chose à savoir.
CWSpear
38

S'il vous plaît, ne le faites pas comme ça (en passant GET var pour faire partie d'un appel système). Utilisez ZipArchive plutôt .

Ainsi, votre code devrait ressembler à:

$zipArchive = new ZipArchive();
$result = $zipArchive->open($_GET["master"]);
if ($result === TRUE) {
    $zipArchive ->extractTo("my_dir");
    $zipArchive ->close();
    // Do something else on success
} else {
    // Do something on error
}

Et pour répondre à votre question, votre erreur est «quelque chose $ var quelque chose d'autre» devrait être «quelque chose $ var quelque chose d'autre» (entre guillemets).

Aleksandar Vucetic
la source
3
+1 Oups, désolé d'avoir cloué sur la même réponse cinq minutes plus tard. Je ne vous y ai pas vu :)
rdlowrey
10

Utiliser getcwd()pour extraire dans le même répertoire

<?php
$unzip = new ZipArchive;
$out = $unzip->open('wordpress.zip');
if ($out === TRUE) {
  $unzip->extractTo(getcwd());
  $unzip->close();
  echo 'File unzipped';
} else {
  echo 'Error';
}
?>
Rubyx
la source
5

Essayez simplement ceci yourDestinationDir est la destination vers laquelle extraire ou supprimez -d yourDestinationDir pour extraire vers le répertoire racine.

$master = 'someDir/zipFileName';
$data = system('unzip -d yourDestinationDir '.$master.'.zip');
Samuel Kwame Antwi
la source
1
J'ai utilisé yourDestinationDircomme session_save_path() . DIRECTORY_SEPARATOR . "$name" . DIRECTORY_SEPARATOR$nameest le dossier cible pour décompresser dans le dossier de session.
Ramratan Gupta
1
Soyez très prudent lorsque vous traitez des fonctions système ou exécutables qui contiennent des variables! Il peut littéralement donner une ligne de commande gratuite de votre serveur à un pirate.
maxime
@maxime Comment est-ce possible? veuillez expliquer parce que je pense que le php est une mesure pour empêcher cela de se produire. Soutenez vos affirmations par des faits
Samuel Kwame Antwi
@SamuelKwameAntwi exec et system appellent le shell du système, avec l'utilisateur php. Donc, si votre utilisateur est www, vous pouvez faire tout ce que l'utilisateur unix "www" peut faire sur la ligne de commande, y compris la suppression de fichiers ou de répertoires. C'est vraiment pire si votre utilisateur php est root. Vous pouvez trouver plus d'informations à ce sujet ici: stackoverflow.com/questions/3115559/exploitable-php-functions
maxime
5

J'ai mis à jour la réponse de @rdlowrey à un code plus propre et meilleur, cela décompressera un fichier dans le répertoire actuel en utilisant __DIR__.

<?php 
    // config
    // -------------------------------
    // only file name + .zip
    $zip_filename = "YOURFILENAME.zip";
?>

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8' >
    <title>Unzip</title>
    <style>
        body{
            font-family: arial, sans-serif;
            word-wrap: break-word;
        }
        .wrapper{
            padding:20px;
            line-height: 1.5;
            font-size: 1rem;
        }
        span{
            font-family: 'Consolas', 'courier new', monospace;
            background: #eee;
            padding:2px;
        }
    </style>
</head>
<body>
    <div class="wrapper">
        <?php
        echo "Unzipping <span>" .__DIR__. "/" .$zip_filename. "</span> to <span>" .__DIR__. "</span><br>";
        echo "current dir: <span>" . __DIR__ . "</span><br>";
        $zip = new ZipArchive;
        $res = $zip->open(__DIR__ . '/' .$zip_filename);
        if ($res === TRUE) {
          $zip->extractTo(__DIR__);
          $zip->close();
          echo '<p style="color:#00C324;">Extract was successful! Enjoy ;)</p><br>';
        } else {
          echo '<p style="color:red;">Zip file not found!</p><br>';
        }
        ?>
        End Script.
    </div>
</body>
</html> 
Morteza Ziyae
la source
2

PHP a sa propre classe intégrée qui peut être utilisée pour décompresser ou extraire le contenu d'un fichier zip. La classe est ZipArchive. Ci-dessous se trouve le code PHP simple et basique qui va extraire un fichier zip et le placer dans un répertoire spécifique:

<?php
$zip_obj = new ZipArchive;
$zip_obj->open('dummy.zip');
$zip_obj->extractTo('directory_name/sub_dir');
?>

Si vous voulez des fonctionnalités avancées, voici le code amélioré qui vérifiera si le fichier zip existe ou non:

<?php
$zip_obj = new ZipArchive;
if ($zip_obj->open('dummy.zip') === TRUE) {
   $zip_obj->extractTo('directory/sub_dir');
   echo "Zip exists and successfully extracted";
}
else {
   echo "This zip file does not exists";
}
?>

Source: Comment décompresser ou extraire des fichiers zip en PHP?

Faruque Ahamed Mollick
la source
0

J'ai mis à jour la réponse de Morteza Ziaeemehr à un code plus propre et meilleur, cela décompressera un fichier fourni dans le formulaire dans le répertoire actuel en utilisant DIR .

<!DOCTYPE html>
<html>
<head>
  <meta charset='utf-8' >
  <title>Unzip</title>
  <style>
  body{
    font-family: arial, sans-serif;
    word-wrap: break-word;
  }
  .wrapper{
    padding:20px;
    line-height: 1.5;
    font-size: 1rem;
  }
  span{
    font-family: 'Consolas', 'courier new', monospace;
    background: #eee;
    padding:2px;
  }
  </style>
</head>
<body>
  <div class="wrapper">
    <?php
    if(isset($_GET['page']))
    {
      $type = $_GET['page'];
      global $con;
      switch($type)
        {
            case 'unzip':
            {    
                $zip_filename =$_POST['filename'];
                echo "Unzipping <span>" .__DIR__. "/" .$zip_filename. "</span> to <span>" .__DIR__. "</span><br>";
                echo "current dir: <span>" . __DIR__ . "</span><br>";
                $zip = new ZipArchive;
                $res = $zip->open(__DIR__ . '/' .$zip_filename);
                if ($res === TRUE) 
                {
                    $zip->extractTo(__DIR__);
                    $zip->close();
                    echo '<p style="color:#00C324;">Extract was successful! Enjoy ;)</p><br>';
                } 
                else 
                {
                    echo '<p style="color:red;">Zip file not found!</p><br>';
                }
                break;
            }
        }
    }
?>
End Script.
</div>
    <form name="unzip" id="unzip" role="form">
        <div class="body bg-gray">
            <div class="form-group">
                <input type="text" name="filename" class="form-control" placeholder="File Name (with extension)"/>
            </div>        
        </div>
    </form>

<script type="application/javascript">
$("#unzip").submit(function(event) {
  event.preventDefault();
    var url = "function.php?page=unzip"; // the script where you handle the form input.
    $.ajax({
     type: "POST",
     url: url,
     dataType:"json",
           data: $("#unzip").serialize(), // serializes the form's elements.
           success: function(data)
           {
               alert(data.msg); // show response from the php script.
               document.getElementById("unzip").reset();
             }

           });

    return false; // avoid to execute the actual submit of the form
  });
</script>
</body>
</html> 
Varun Naharia
la source
0

Changez juste

system('unzip $master.zip');

À celui-ci

system('unzip ' . $master . '.zip');

ou celui-ci

system("unzip {$master}.zip");

sh4nn0nb1t
la source
6
Bien que cela puisse résoudre le problème qu'il rencontrait, jetez un œil aux autres réponses pour voir pourquoi il s'agit d'un mauvais conseil.
rjdown
0

vous pouvez utiliser la fonction préemballée

function unzip_file($file, $destination){
    // create object
    $zip = new ZipArchive() ;
    // open archive
    if ($zip->open($file) !== TRUE) {
        return false;
    }
    // extract contents to destination directory
    $zip->extractTo($destination);
    // close archive
    $zip->close();
        return true;
}

Comment l'utiliser.

if(unzip_file($file["name"],'uploads/')){
echo 'zip archive extracted successfully';
}else{
  echo 'zip archive extraction failed';
}
user889030
la source
0

Utilisez ci-dessous le code PHP, avec le nom de fichier dans le paramètre URL "nom"

<?php

$fileName = $_GET['name'];

if (isset($fileName)) {


    $zip = new ZipArchive;
    $res = $zip->open($fileName);
    if ($res === TRUE) {
      $zip->extractTo('./');
      $zip->close();
      echo 'Extracted file "'.$fileName.'"';
    } else {
      echo 'Cannot find the file name "'.$fileName.'" (the file name should include extension (.zip, ...))';
    }
}
else {
    echo 'Please set file name in the "name" param';
}

?>
huync
la source
0

Fonction PHP simple à décompresser. Veuillez vous assurer que l'extension zip est installée sur votre serveur.

/**
 * Unzip
 * @param string $zip_file_path Eg - /tmp/my.zip
 * @param string $extract_path Eg - /tmp/new_dir_name
 * @return boolean
 */
function unzip(string $zip_file_path, string $extract_dir_path) {
    $zip = new \ZipArchive;
    $res = $zip->open($zip_file_path);
    if ($res === TRUE) {
        $zip->extractTo($extract_dir_path);
        $zip->close();
        return TRUE;
    } else {
        return FALSE;
    }
}
M_R_K
la source
-3

Utilisez simplement ceci:

  $master = $_GET["master"];
  system('unzip' $master.'.zip'); 

dans votre code $masterest passé sous forme de chaîne, le système recherchera un fichier appelé$master.zip

  $master = $_GET["master"];
  system('unzip $master.zip'); `enter code here`
Dennis Kiptugen
la source
5
Juste complètement faux. 'unzip' $masterne fonctionnerait pas sauf si vous avez ajouté un espace après la décompression et ajouté un point après le guillemet simple. Il aurait été beaucoup plus facile de suggérer system("unzip $master.zip")des guillemets doubles, ou au moins une réponse valide.
Nicholas Blasgen
1
Il vaut mieux utiliser les fonctions système PHP que de s'appuyer sur les fonctions système.
Sloan Thrasher
Comme souligné dans la réponse acceptée - veuillez désinfecter l'entrée utilisateur, n'importe qui peut ajouter n'importe quoi à cette $_GETchaîne de requête et injecter son propre code à l' systemappel
jg2703