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,


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

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


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

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

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> 

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?


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> 

0

Po prostu zmień

system('unzip $master.zip');

Do tego

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

albo ten

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


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

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

?>

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

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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.