Descomprima un archivo con php


199

Quiero descomprimir un archivo y esto funciona bien

system('unzip File.zip');

Pero necesito pasar el nombre del archivo a través de la URL y no puedo hacerlo funcionar, esto es lo que tengo.

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

¿Qué me estoy perdiendo? Sé que tiene que ser algo pequeño y estúpido que estoy pasando por alto.

Gracias,


35
Las comillas dobles evalúan las variables; las comillas simples no. PERO: tenga cuidado, ya que simplemente pasar alguna entrada a una llamada del sistema podría ser bastante peligroso.
Wiseguy

25
Debo decir que no me gusta el tono hostil de algunos comentarios. Si ustedes se dan cuenta de que le falta algo, entonces cuéntele al respecto. Todos echamos de menos algo en algún momento.
Sebastian Mach

El error aquí es simple. Está intentando utilizar la interpolación de cadenas con comillas simples en lugar de comillas dobles. La interpolación de cadenas no funciona con comillas simples porque se usa para literales de cadena. Por lo tanto, cambiar su código a system("unzip $master.zip");debería funcionar.
Asier Paz

Respuestas:


500

¿Solo puedo suponer que su código proviene de un tutorial en algún lugar en línea? En ese caso, buen trabajo tratando de resolverlo por ti mismo. Por otro lado, el hecho de que este código se pueda publicar en línea en algún lugar como la forma correcta de descomprimir un archivo es un poco aterrador.

PHP tiene extensiones incorporadas para manejar archivos comprimidos. No debería haber necesidad de usar systemllamadas para esto. ZipArchivedocs es una opción.

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

Además, como han comentado otros, $HTTP_GET_VARSha quedado en desuso desde la versión 4.1 ... que fue hace mucho tiempo. No lo uses Utilice el $_GETsuperglobal en su lugar.

Finalmente, tenga mucho cuidado al aceptar cualquier entrada que se pase a un script a través de una $_GETvariable.

SIEMPRE DESINFECCIONE LA ENTRADA DE USUARIO.


ACTUALIZAR

Según su comentario, la mejor manera de extraer el archivo zip en el mismo directorio en el que reside es determinar la ruta de acceso dura al archivo y extraerlo específicamente a esa ubicación. Entonces, podrías hacer:

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

Gracias por el consejo Soy nuevo en esto y me estoy dando cuenta de todo. Con su código, ¿cómo puedo hacer que se descomprima en la misma carpeta en la que se encuentra el archivo comprimido?
BostonBB

2
Bueno, hay una diferencia entre el directorio de trabajo actual de su script y el directorio donde reside el archivo zip. Si el archivo zip está en el mismo directorio que la secuencia de comandos que podría hacer $zip->extractTo('./');, sin embargo, este no es el caso. Una mejor opción es determinar la ubicación del archivo zip en el sistema de archivos y extraerlo allí. Actualizaré mi respuesta para demostrar.
rdlowrey

¿Qué sucede si no tiene la clase ZipArchive disponible? Estoy trabajando en un sitio con alojamiento de basura y recibo el Fatal error: Class 'ZipArchive' not founderror que intento con este script :-( ¿Hay alguna opción en ese momento?
CWSpear

2
@CWSpear necesitará lazlib biblioteca subyacente para realizar prácticamente cualquier operación de compresión / descompresión con PHP. Incluso para hacer llamadas al sistema, necesitaría tener la biblioteca subyacente. Sin embargo, esto es algo muy ubicuo, y no tenerlo es la excepción. Si estás en un alojamiento compartido, deberían instalarlo por ti. De lo contrario, solo busque en Google algo como "Cómo instalar el soporte de funciones Zip para PHP"
rdlowrey

Sí, es un alojamiento bastante barato como me han dicho. De todos modos, gracias por la respuesta, es bueno saberlo.
CWSpear

38

Por favor, no lo haga así (pasar GET var para ser parte de una llamada al sistema). Use ZipArchive en su lugar.

Entonces, su código debería verse así:

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

Y para responder a su pregunta, su error es 'algo $ var otra cosa' debería ser "algo $ var otra cosa" (entre comillas dobles).


3
+1 Oops, perdón por agregar básicamente la misma respuesta cinco minutos después. No te vi allí :)
rdlowrey

10

Utilizando getcwd()para extraer en el mismo directorio

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

5

Simplemente intente esto yourDestinationDir es el destino para extraer o eliminar -d yourDestinationDir para extraer al directorio raíz.

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

1
Solía yourDestinationDircomo session_save_path() . DIRECTORY_SEPARATOR . "$name" . DIRECTORY_SEPARATOR dónde $nameestá la carpeta de destino para descomprimir en la carpeta de sesión.
Ramratan Gupta

1
¡Tenga mucho cuidado cuando maneje funciones de sistema o ejecutivas que contienen variables! Literalmente puede dar una línea de comando gratuita desde su servidor a un hacker.
maxime

@maxime ¿Cómo es eso posible? explique porque creo que php es una medida para evitar que eso suceda. Respalde sus afirmaciones con hechos
Samuel Kwame Antwi

@SamuelKwameAntwi exec y el sistema están llamando al shell del sistema, con el usuario php. Por lo tanto, si su usuario es www, puede hacer todo lo que el usuario de Unix "www" puede hacer en la línea de comandos, incluida la eliminación de archivos o directorios. Es realmente peor si su usuario php es root. Puede encontrar más información al respecto allí: stackoverflow.com/questions/3115559/exploitable-php-functions
maxime

5

Actualicé la respuesta de @rdlowrey a un código más limpio y mejor. Esto descomprimirá un archivo en el directorio actual 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 tiene su propia clase incorporada que puede usarse para descomprimir o extraer contenidos de un archivo zip. La clase es ZipArchive. A continuación se muestra el código PHP simple y básico que extraerá un archivo zip y lo colocará en un directorio específico:

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

Si desea algunas funciones avanzadas, a continuación se encuentra el código mejorado que verificará si el archivo zip existe o no:

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

Fuente: ¿Cómo descomprimir o extraer archivos zip en PHP?


0

Actualicé la respuesta de Morteza Ziaeemehr a un código más limpio y mejor. Esto descomprimirá un archivo proporcionado dentro del formulario en el directorio actual 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

Solo cambia

system('unzip $master.zip');

A este

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

o este

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


66
Si bien esto puede solucionar el problema que estaba teniendo, eche un vistazo a las otras respuestas para ver por qué este es un mal consejo.
rjdown

0

puedes usar la función preempaquetada

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

Cómo usarlo.

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

0

Use el siguiente código PHP, con el nombre del archivo en el parámetro de URL "nombre"

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

Función PHP simple para descomprimir. Asegúrese de tener instalada la extensión zip en su 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

Solo usa esto:

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

en su código $masterse pasa como una cadena, el sistema buscará un archivo llamado$master.zip

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

55
Simplemente completamente equivocado. 'unzip' $masterno funcionaría a menos que agregue un espacio después de descomprimir y agregue un punto después de la comilla simple. Hubiera sido mucho más fácil sugerir system("unzip $master.zip")con comillas dobles, o al menos una respuesta válida.
Nicholas Blasgen

1
Es mejor usar las funciones del sistema PHP que confiar en las funciones del sistema.
Sloan Thrasher

Como se señala en la respuesta aceptada - por favor, la entrada del usuario desinfectar, cualquiera puede añadir nada a esta $_GETcadena de consulta e inyectar su propio código a la systemllamada
jg2703
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.