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,


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

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).


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

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');

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> 

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?


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> 

0

Apenas mude

system('unzip $master.zip');

Para este

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

ou este

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


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

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

?>

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

-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`

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.