Rozpakuj plik za pomocą php

198

Chcę rozpakować plik, a to działa dobrze

system('unzip File.zip');

Ale muszę przekazać nazwę pliku przez adres URL i nie mogę go uruchomić, oto co mam.

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

czego mi brakuje? Wiem, że to musi być coś małego i głupiego, co przeoczam.

Dziękuję Ci,

BostonBB
źródło
35
Podwójne cudzysłowy oceniają zmienne; pojedyncze cytaty nie. ALE - bądź ostrożny, ponieważ przekazanie danych wejściowych do wywołania systemowego może być dość niebezpieczne.
Wiseguy,
25
Muszę powiedzieć, że nie podoba mi się wrogi ton niektórych komentarzy. Jeśli zdacie sobie sprawę, że on / ona czegoś brakuje, to po prostu powiedzcie o tym. W pewnym momencie wszyscy coś przeoczyliśmy.
Sebastian Mach
Błąd tutaj jest prosty. Próbujesz użyć interpolacji ciągów z prostymi cudzysłowami zamiast podwójnych cudzysłowów. Interpolacja ciągów znaków nie działa z prostymi cudzysłowami, ponieważ jest używana do literałów ciągów. Tak więc zmiana kodu na system("unzip $master.zip");powinna działać.
Asier Paz

Odpowiedzi:

500

Mogę tylko założyć, że Twój kod pochodzi z samouczka w Internecie? W takim razie dobra robota próbuje to samemu rozwiązać. Z drugiej strony fakt, że ten kod może być gdzieś opublikowany online jako właściwy sposób rozpakowania pliku, jest nieco przerażający.

PHP ma wbudowane rozszerzenia do obsługi skompresowanych plików. W tym celu nie powinno być potrzeby korzystania z systempołączeń. ZipArchiveDokumenty to jedna z opcji.

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

Ponadto, jak skomentowali inni, $HTTP_GET_VARSjest on przestarzały od wersji 4.1 ... która była naprawdę dawno temu. Nie używaj tego. $_GETZamiast tego użyj superglobalu.

Wreszcie, bądź bardzo ostrożny przy akceptowaniu wszelkich danych wejściowych przekazywanych do skryptu przez $_GETzmienną.

ZAWSZE ODCZYTAJ WEJŚCIE UŻYTKOWNIKA.


AKTUALIZACJA

Zgodnie z komentarzem najlepszym sposobem na wyodrębnienie pliku zip do tego samego katalogu, w którym się znajduje, jest określenie twardej ścieżki do pliku i wyodrębnienie go konkretnie do tej lokalizacji. Więc możesz zrobić:

// 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
źródło
Dziękuję za radę. Jestem w tym nowy i po prostu wszystko rozgryzam. Jak mogę sprawić, by Twój kod rozpakował się w tym samym folderze, w którym znajduje się skompresowany plik?
BostonBB,
2
Istnieje różnica między bieżącym katalogiem roboczym skryptu a katalogiem, w którym znajduje się plik zip. Jeśli plik zip znajduje się w tym samym katalogu co skrypt, który możesz wykonać. $zip->extractTo('./');Prawdopodobnie tak nie jest. Lepszą opcją jest określenie lokalizacji pliku zip w systemie plików i wyodrębnienie go. Zaktualizuję moją odpowiedź, aby zademonstrować.
rdlowrey
Co jeśli nie masz dostępnej klasy ZipArchive? Pracuję na stronie z bzdura gospodarzem i otrzymuję Fatal error: Class 'ZipArchive' not foundbłąd, który próbuję tego skryptu :-( Czy jest jakaś opcja w tym momencie?
CWSpear
2
@CWSpear będziesz potrzebować podstawowejzlib biblioteki, aby wykonać prawie wszystkie operacje kompresji / dekompresji za pomocą PHP. Nawet do wykonywania wywołań systemowych potrzebujesz podstawowej biblioteki. Jest to jednak bardzo wszechobecna rzecz, a jej brak jest wyjątkiem. Jeśli korzystasz z hostingu współdzielonego, powinni go zainstalować. W przeciwnym razie, po prostu google coś takiego jak „Jak zainstalować obsługę funkcji Zip dla PHP”
rdlowrey
Tak, to całkiem tani hosting, jak mi powiedziano. W każdym razie dzięki za odpowiedź, warto wiedzieć.
CWSpear,
38

Nie rób tego w ten sposób (przekazanie GET var jako części wywołania systemowego). Zamiast tego użyj ZipArchive .

Twój kod powinien więc wyglądać następująco:

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

Aby odpowiedzieć na twoje pytanie, twój błąd brzmi: „coś $ var coś innego” powinno być „coś $ var coś innego” (w podwójnych cudzysłowach).

Aleksandar Vucetic
źródło
3
+1 Ups, przepraszam, że dostałem tę samą odpowiedź pięć minut później. Nie widziałem cię tam :)
rdlowrey
10

Używanie getcwd()do wypakowywania w tym samym katalogu

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

Po prostu wypróbuj ten twójDestinationDir jest miejscem docelowym do wyodrębnienia lub usunięcia -d yourDestinationDir do wyodrębnienia do katalogu głównego.

$master = 'someDir/zipFileName';
$data = system('unzip -d yourDestinationDir '.$master.'.zip');
Samuel Kwame Antwi
źródło
1
Użyłem yourDestinationDirjako session_save_path() . DIRECTORY_SEPARATOR . "$name" . DIRECTORY_SEPARATOR gdzie $namejest folder docelowy do rozpakowania w folderze sesji.
Ramratan Gupta
1
Bądź bardzo ostrożny, mając do czynienia z funkcjami systemowymi lub exec, które zawierają zmienne! Może dosłownie dać hakerowi darmowy wiersz poleceń z twojego serwera.
maxime
@maxime Jak to możliwe? proszę wyjaśnij, ponieważ myślę, że php jako środek, aby temu zapobiec. Poprzyj swoje roszczenia faktami
Samuel Kwame Antwi
@SamuelKwameAntwi exec i system wywołują powłokę systemową z użytkownikiem php. Tak więc, jeśli twoim użytkownikiem jest www, możesz zrobić wszystko, co użytkownik unix „www” może zrobić w wierszu poleceń, łącznie z usuwaniem plików lub katalogów. To naprawdę najgorsze, jeśli użytkownik php jest rootem. Więcej informacji na ten temat można znaleźć tutaj: stackoverflow.com/questions/3115559/exploitable-php-functions
maksime
5

Zaktualizowałem odpowiedź @rdlowrey na czystszy i lepszy kod. To rozpakuje plik do bieżącego katalogu przy użyciu __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
źródło
2

PHP ma własną wbudowaną klasę, której można użyć do rozpakowania lub wypakowania zawartości z pliku zip. Ta klasa to ZipArchive. Poniżej znajduje się prosty i podstawowy kod PHP, który rozpakuje plik zip i umieści go w określonym katalogu:

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

Jeśli chcesz jakieś zaawansowane funkcje, poniżej znajduje się ulepszony kod, który sprawdzi, czy plik zip istnieje, czy nie:

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

Źródło: Jak rozpakować lub wyodrębnić pliki zip w PHP?

Faruque Ahamed Mollick
źródło
0

Zaktualizowałem odpowiedź Morteza Ziaeemehr do czystszego i lepszego kodu. To rozpakuje plik dostarczony w formularzu do bieżącego katalogu za pomocą 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
źródło
0

Po prostu zmień

system('unzip $master.zip');

Do tego

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

albo ten

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

sh4nn0nb1t
źródło
6
Chociaż może to rozwiązać problem, który miał, spójrz na inne odpowiedzi, aby zobaczyć, dlaczego jest to zła rada.
rjdown
0

możesz użyć funkcji paczkowanej

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

Jak tego użyć.

if(unzip_file($file["name"],'uploads/')){
echo 'zip archive extracted successfully';
}else{
  echo 'zip archive extraction failed';
}
użytkownik889030
źródło
0

Użyj poniżej kodu PHP, z nazwą pliku w parametrze URL „nazwa”

<?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
źródło
0

Prosta funkcja PHP do rozpakowania. Upewnij się, że masz rozszerzenie zip zainstalowane na serwerze.

/**
 * 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
źródło
-3

Po prostu użyj tego:

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

w kodzie $masterjest przekazywany jako ciąg znaków, system będzie szukał pliku o nazwie$master.zip

  $master = $_GET["master"];
  system('unzip $master.zip'); `enter code here`
Dennis Kiptugen
źródło
5
Zupełnie źle. 'unzip' $masternie będzie działać, chyba że dodasz spację po rozpakowaniu i dodasz kropkę po pojedynczym cudzysłowie. Byłoby o wiele łatwiej zasugerować system("unzip $master.zip")z podwójnymi cytatami lub przynajmniej prawidłową odpowiedzią.
Nicholas Blasgen
1
Lepiej jest korzystać z funkcji systemowych PHP niż polegać na funkcjach systemowych.
Sloan Thrasher
Jak podkreślono w zaakceptowanej odpowiedzi - proszę oczyścić dane wejściowe użytkownika, każdy może dodać dowolną część do tego $_GETciągu zapytania i wstrzyknąć własny kod do systemwywołania
jg2703