Decomprimi un file con php


199

Voglio decomprimere un file e questo funziona bene

system('unzip File.zip');

Ma devo passare il nome del file attraverso l'URL e non riesco a farlo funzionare, questo è quello che ho.

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

Cosa mi sto perdendo? So che deve essere qualcosa di piccolo e stupido che sto trascurando.

Grazie,


35
Le virgolette doppie valutano le variabili; le virgolette singole no. MA - stai attento, dato che semplicemente passare alcuni input a una chiamata di sistema potrebbe essere abbastanza pericoloso.
Wiseguy,

25
Devo dire che non mi piace il tono ostile di alcuni commenti. Se capite che sta perdendo qualcosa, allora diteglielo. Ci manca qualcosa a un certo punto.
Sebastian Mach,

L'errore qui è semplice. Stai tentando di utilizzare l'interpolazione di stringhe con virgolette semplici anziché doppie. L'interpolazione di stringhe non funziona con virgolette semplici perché viene utilizzata per valori letterali di stringa. Quindi, cambiare il codice in system("unzip $master.zip");dovrebbe funzionare.
Asier Paz,

Risposte:


500

Posso solo supporre che il tuo codice provenga da un tutorial da qualche parte online? In quel caso, buon lavoro cercando di capirlo da solo. D'altra parte, il fatto che questo codice possa effettivamente essere pubblicato online da qualche parte come il modo corretto di decomprimere un file è un po 'spaventoso.

PHP ha estensioni integrate per gestire i file compressi. Non dovrebbe essere necessario utilizzare le systemchiamate per questo. ZipArchivedocumenti è un'opzione.

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

Inoltre, come altri hanno commentato, $HTTP_GET_VARSè stato deprecato dalla versione 4.1 ... che è stata molto tempo fa. Non usarlo. Usa $_GETinvece il superglobal.

Infine, fai molta attenzione ad accettare qualunque input venga passato a uno script tramite una $_GETvariabile.

SANIFICARE SEMPRE L'INGRESSO DELL'UTENTE.


AGGIORNARE

Secondo il tuo commento, il modo migliore per estrarre il file zip nella stessa directory in cui risiede è determinare il percorso difficile del file ed estrarlo specificamente in quella posizione. Quindi, potresti fare:

// 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";
}

Grazie per il consiglio. Sono nuovo di questo e sto solo scoprendo tutto. Con il tuo codice, come posso fare per decomprimerlo nella stessa cartella in cui si trova il file zippato?
Boston,

2
Bene, c'è una differenza tra l'attuale directory di lavoro dello script e la directory in cui risiede il file zip. Se il file zip si trova nella stessa directory dello script che potresti fare $zip->extractTo('./');Tuttavia, probabilmente non è così. Un'opzione migliore è determinare la posizione del file zip nel filesystem ed estrarlo lì. Aggiornerò la mia risposta per dimostrare.
rdlowrey,

Cosa succede se non si dispone della classe ZipArchive disponibile? Sto lavorando su un sito con crap hosting e ricevo l' Fatal error: Class 'ZipArchive' not founderrore che provo con questo script :-( C'è qualche opzione a quel punto?
CWSpear

2
@CWSpear avrai bisogno dellazlib libreria sottostante per eseguire praticamente qualsiasi operazione di compressione / decompressione con PHP. Anche per effettuare chiamate di sistema dovresti avere la libreria sottostante. Questa è una cosa molto onnipresente, e non averla fa eccezione. Se usi l'hosting condiviso, dovrebbero installarlo per te. Altrimenti, basta google qualcosa come "Come installare il supporto delle funzioni Zip per PHP"
rdlowrey,

Sì, è un hosting piuttosto economico come mi è stato detto. Comunque, grazie per la risposta, è una buona cosa sapere.
CWSpear

38

Per favore, non farlo in questo modo (passando GET var per far parte di una chiamata di sistema). Utilizzare invece ZipArchive .

Quindi, il tuo codice dovrebbe apparire come:

$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
}

E per rispondere alla tua domanda, il tuo errore è "qualcosa $ var qualcos'altro" dovrebbe essere "qualcosa $ var qualcos'altro" (tra virgolette doppie).


3
+1 Oops, scusami per aver aderito sostanzialmente alla stessa risposta cinque minuti dopo. Non ti ho visto lì :)
rdlowrey

10

utilizzando getcwd() per estrarre nella stessa directory

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

5

Basta provare questo yourDestinationDir è la destinazione da estrarre o rimuovere -d yourDestinationDir da estrarre nella directory principale.

$master = 'someDir/zipFileName';
$data = system('unzip -d yourDestinationDir '.$master.'.zip');

1
Ho usato yourDestinationDircome session_save_path() . DIRECTORY_SEPARATOR . "$name" . DIRECTORY_SEPARATOR dov'è la $namecartella di destinazione da decomprimere nella cartella della sessione.
Ramratan Gupta,

1
Fai molta attenzione quando hai a che fare con funzioni di sistema o exec che contengono variabili! Può letteralmente fornire una riga di comando gratuita dal tuo server a un hacker.
maxime

@maxime Com'è possibile? per favore spiega perché penso che PHP sia una misura per impedire che ciò accada. Appoggia le tue affermazioni con i fatti
Samuel Kwame Antwi il

@SamuelKwameAntwi exec e system stanno chiamando la shell di sistema, con l'utente php. Quindi, se il tuo utente è www, puoi fare tutto ciò che l'utente unix "www" può fare dalla riga di comando, inclusa la rimozione di file o directory. È davvero peggio se l'utente php è root. Puoi trovare maggiori informazioni a riguardo qui: stackoverflow.com/questions/3115559/exploitable-php-functions
maxime

5

Ho aggiornato la risposta di @rdlowrey a un codice più pulito e migliore, questo decomprimerà un file nella directory corrente usando __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> 

2

PHP ha la sua classe integrata che può essere utilizzata per decomprimere o estrarre contenuti da un file zip. La classe è ZipArchive. Di seguito è riportato il codice PHP semplice e di base che estrae un file zip e lo inserisce in una directory specifica:

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

Se si desidera alcune funzionalità avanzate, di seguito è riportato il codice migliorato che controllerà se il file zip esiste o meno:

<?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";
}
?>

Fonte: Come decomprimere o estrarre i file zip in PHP?


0

Ho aggiornato la risposta di Morteza Ziaeemehr a un codice più pulito e migliore, questo decomprimerà un file fornito nella forma nella directory corrente usando 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> 

0

Basta cambiare

system('unzip $master.zip');

A questo

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

o questo

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


6
Sebbene ciò possa risolvere il problema che stava riscontrando, dai un'occhiata alle altre risposte per capire perché si tratta di un cattivo consiglio.
rjdown

0

puoi usare la funzione preconfezionata

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;
}

Come usarlo.

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

0

Usa sotto il codice PHP, con il nome del file nell'URL param "name"

<?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';
}

?>

0

Semplice funzione PHP da decomprimere. Assicurati di avere l'estensione zip installata sul tuo server.

/**
 * 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;
    }
}

-3

Usa questo:

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

nel tuo codice $masterviene passato come una stringa, il sistema cercherà un file chiamato$master.zip

  $master = $_GET["master"];
  system('unzip $master.zip'); `enter code here`

5
Completamente sbagliato. 'unzip' $masternon funzionerebbe a meno che tu non abbia aggiunto uno spazio dopo averlo decompresso e aggiunto un punto dopo la singola citazione. Sarebbe stato molto più semplice suggerire system("unzip $master.zip")con virgolette doppie o almeno una risposta valida.
Nicholas Blasgen,

1
È meglio usare le funzioni del sistema PHP piuttosto che fare affidamento sulle funzioni del sistema.
Sloan Thrasher,

Come sottolineato nella risposta accettata, per favore disinfetta l'input dell'utente, chiunque può aggiungere qualsiasi cosa a questa $_GETstringa di query e iniettare il proprio codice alla systemchiamata
jg2703
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.