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.