Descompacte um arquivo com php

198

Quero descompactar um arquivo e isso funciona bem

system('unzip File.zip');

Mas preciso passar o nome do arquivo pela URL e não consigo fazê-lo funcionar, é isso que tenho.

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

o que estou perdendo? Eu sei que tem que ser algo pequeno e estúpido que estou ignorando.

Obrigado,

BostonBB
fonte
35
Aspas duplas avaliam variáveis; aspas simples não. MAS - tenha cuidado, pois simplesmente passar alguma entrada para uma chamada do sistema pode ser bastante perigoso.
Wiseguy
25
Devo dizer que não gosto do tom hostil de alguns comentários. Se vocês perceberem que ela está perdendo alguma coisa, então apenas conte a ela. Todos nós sentimos falta de algo em algum momento.
Sebastian Mach
O erro aqui é simples. Você está tentando usar a interpolação de seqüência de caracteres com aspas simples em vez de aspas duplas. A interpolação de cadeias não funciona com aspas simples porque é usada para literais de cadeias. Portanto, alterar seu código para system("unzip $master.zip");deve funcionar.
Asier Paz

Respostas:

500

Só posso supor que seu código veio de um tutorial em algum lugar online? Nesse caso, bom trabalho tentando descobrir por si mesmo. Por outro lado, o fato de esse código poder ser publicado on-line em algum lugar, pois a maneira correta de descompactar um arquivo é um pouco assustador.

O PHP possui extensões integradas para lidar com arquivos compactados. Não deve haver necessidade de usar systemchamadas para isso. ZipArchivedocs é uma opção.

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

Além disso, como outros comentaram, $HTTP_GET_VARSfoi preterido desde a versão 4.1 ... que foi há muito tempo. Não use. Use o $_GETsuperglobal em seu lugar.

Por fim, tenha muito cuidado ao aceitar qualquer entrada que seja passada para um script por meio de uma $_GETvariável.

SANITIZE SEMPRE A ENTRADA DO USUÁRIO.


ATUALIZAR

Conforme seu comentário, a melhor maneira de extrair o arquivo zip para o mesmo diretório em que reside é determinar o caminho difícil para o arquivo e extraí-lo especificamente para esse local. Então, você poderia fazer:

// 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
fonte
Obrigado pelo conselho. Eu sou novo nisso e estou apenas descobrindo tudo. Com o seu código, como posso descompactar na mesma pasta em que o arquivo compactado está?
BostonBB
2
Bem, há uma diferença entre o diretório de trabalho atual do seu script e o diretório em que o arquivo zip reside. Se o arquivo zip estiver no mesmo diretório que o script que você pode $zip->extractTo('./');executar, no entanto, isso provavelmente não é o caso. Uma opção melhor é determinar a localização do arquivo zip no sistema de arquivos e extraí-lo lá. Vou atualizar minha resposta para demonstrar.
precisa saber é o seguinte
E se você não tiver a classe ZipArchive disponível? Eu estou trabalhando em um site com porcaria hospedagem e eu recebo o Fatal error: Class 'ZipArchive' not founderro que eu tento este script :-( Existe alguma opção nesse ponto?
CWSpear
2
@ CWSpear, você precisará dazlib biblioteca subjacente para executar praticamente todas as operações de compactação / descompactação com PHP. Mesmo para fazer chamadas do sistema, você precisa ter a biblioteca subjacente. Isso é algo muito onipresente, e não tê-lo é a exceção. Se você estiver em hospedagem compartilhada, eles devem instalá-lo para você. Caso contrário, apenas google algo como "How to install zip funções de suporte para o PHP"
rdlowrey
Sim, é uma hospedagem muito barata, como me disseram. De qualquer forma, obrigado pela resposta, é bom saber.
CWSpear
38

Por favor, não faça assim (passar GET var para fazer parte de uma chamada de sistema). Use o ZipArchive .

Portanto, seu código deve se parecer com:

$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 para responder sua pergunta, seu erro é 'algo $ var outra coisa' deve ser "algo $ var outra coisa" (entre aspas duplas).

Aleksandar Vucetic
fonte
3
+1 Ops, desculpe-me por seguir basicamente a mesma resposta cinco minutos depois. Não vi você lá :)
rdlowrey
10

Usando getcwd()para extrair no mesmo diretório

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

Simplesmente tente este yourDestinationDir é o destino para extrair ou remover -d yourDestinationDir para extrair para o diretório raiz.

$master = 'someDir/zipFileName';
$data = system('unzip -d yourDestinationDir '.$master.'.zip');
Samuel Kwame Antwi
fonte
1
Eu usei yourDestinationDircomo session_save_path() . DIRECTORY_SEPARATOR . "$name" . DIRECTORY_SEPARATOR onde $nameestá a pasta de destino para descompactar na pasta da sessão.
Ramratan Gupta
1
Tenha muito cuidado ao lidar com funções de sistema ou exec que contêm variáveis! Pode literalmente fornecer uma linha de comando gratuita do seu servidor para um hacker.
maxime
@maxime Como isso é possível? por favor explique porque eu acho o php como medida para impedir que isso aconteça. Backup de suas reivindicações com fatos
Samuel Kwame Antwi
O exec e system do @SamuelKwameAntwi estão chamando o shell do sistema, com o usuário php. Portanto, se seu usuário é www, você pode fazer tudo o que o usuário unix "www" pode fazer na linha de comando, incluindo a remoção de arquivos ou diretórios. É realmente pior se o seu usuário php é root. Você pode encontrar mais informações sobre ele lá: stackoverflow.com/questions/3115559/exploitable-php-functions
maxime
5

Atualizei a resposta de @rdlowrey para um código melhor e mais limpo. Isso descompactará um arquivo no diretório atual 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> 
Morteza Ziyae
fonte
2

O PHP tem sua própria classe embutida que pode ser usada para descompactar ou extrair o conteúdo de um arquivo zip. A classe é ZipArchive. Abaixo está o código PHP simples e básico que extrairá um arquivo zip e o colocará em um diretório específico:

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

Se você deseja alguns recursos avançados, abaixo está o código aprimorado que verificará se o arquivo zip existe ou não:

<?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: Como descompactar ou extrair arquivos zip no PHP?

Faruque Ahamed Mollick
fonte
0

Atualizei a resposta de Morteza Ziaeemehr para um código mais limpo e melhor. Isso descompactará um arquivo fornecido no formulário para o diretório atual usando o 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
fonte
0

Apenas mude

system('unzip $master.zip');

Para este

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

ou este

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

sh4nn0nb1t
fonte
6
Embora isso possa resolver o problema que ele estava tendo, dê uma olhada nas outras respostas para ver por que isso é um mau conselho.
rjdown
0

você pode usar a função pré-embalada

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

Como usá-lo.

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

Use o código PHP abaixo, com o nome do arquivo no parâmetro "nome" da URL

<?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
fonte
0

Função PHP simples para descompactar. Verifique se você possui a extensão zip instalada no seu servidor.

/**
 * 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
fonte
-3

Apenas use isto:

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

no seu código $masteré passado como uma string, o sistema procurará um arquivo chamado$master.zip

  $master = $_GET["master"];
  system('unzip $master.zip'); `enter code here`
Dennis Kiptugen
fonte
5
Apenas completamente errado. 'unzip' $masternão funcionaria, a menos que você tenha adicionado um espaço após descompactar e um período após a aspas simples. Teria sido muito mais fácil sugerir system("unzip $master.zip")com aspas duplas ou pelo menos uma resposta válida.
Nicholas Blasgen
1
É melhor usar as funções do sistema PHP do que confiar nas funções do sistema.
Sloan Thrasher
Como salientado na resposta aceito - por favor, entrada do usuário sanitize, qualquer um pode acrescentar nada a esta $_GETstring de consulta e injetar seu próprio código para a systemchamada
jg2703