Giải nén tệp bằng php


198

Tôi muốn giải nén một tập tin và điều này hoạt động tốt

system('unzip File.zip');

Nhưng tôi cần chuyển tên tệp qua URL và không thể làm cho nó hoạt động, đây là những gì tôi có.

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

Tôi đang thiếu gì? Tôi biết nó phải là một cái gì đó nhỏ bé và ngu ngốc mà tôi đang nhìn.

Cảm ơn bạn,


35
Báo giá kép đánh giá các biến; trích dẫn duy nhất không. NHƯNG - hãy cẩn thận, vì chỉ cần chuyển một số đầu vào cho một cuộc gọi hệ thống có thể khá nguy hiểm.
Wiseguy

25
Phải nói rằng tôi không thích giọng điệu thù địch của một số bình luận. Nếu các bạn nhận ra cô ấy / anh ấy đang thiếu thứ gì đó, thì hãy nói với cô ấy / anh ấy về nó. Tất cả chúng ta đều bỏ lỡ một cái gì đó tại một số điểm.
Sebastian Mach

Lỗi ở đây rất đơn giản. Bạn đang cố gắng sử dụng phép nội suy chuỗi với dấu ngoặc đơn giản thay vì dấu ngoặc kép. Nội suy chuỗi không hoạt động với các trích dẫn đơn giản vì nó được sử dụng cho chuỗi ký tự. Vì vậy, thay đổi mã của bạn để system("unzip $master.zip");làm việc.
Asier Paz

Câu trả lời:


500

Tôi chỉ có thể giả sử mã của bạn đến từ một hướng dẫn ở đâu đó trực tuyến? Trong trường hợp đó, công việc tốt cố gắng tự mình tìm ra nó. Mặt khác, thực tế là mã này thực sự có thể được xuất bản trực tuyến ở đâu đó vì cách chính xác để giải nén một tệp là một chút đáng sợ.

PHP có các phần mở rộng tích hợp để xử lý các tệp nén. Không cần phải sử dụng systemcác cuộc gọi cho việc này. ZipArchivetài liệu là một lựa chọn.

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

Ngoài ra, như những người khác đã nhận xét, $HTTP_GET_VARSđã bị từ chối kể từ phiên bản 4.1 ... đã được xem xét lại từ lâu. Đừng sử dụng nó. Sử dụng $_GETsuperglobal thay thế.

Cuối cùng, hãy thật cẩn thận về việc chấp nhận bất kỳ đầu vào nào được chuyển đến một tập lệnh thông qua một $_GETbiến.

LUÔN LUÔN VỆ SINH NGƯỜI DÙNG.


CẬP NHẬT

Theo nhận xét của bạn, cách tốt nhất để trích xuất tệp zip vào cùng thư mục chứa nó là xác định đường dẫn cứng đến tệp và trích xuất cụ thể đến vị trí đó. Vì vậy, bạn có thể làm:

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

Cám ơn bạn đã cho lời khuyên. Tôi mới làm điều này và chỉ cần tìm ra mọi thứ. Với mã của bạn, làm thế nào tôi có thể giải nén nó trong cùng một thư mục tệp được nén?
BostonBB

2
Chà, có một sự khác biệt giữa thư mục làm việc hiện tại của tập lệnh của bạn và thư mục chứa tệp zip. Nếu tệp zip nằm trong cùng thư mục với tập lệnh bạn có thể làm $zip->extractTo('./');Tuy nhiên, đây có thể không phải là trường hợp. Một lựa chọn tốt hơn là xác định vị trí của tệp zip trong hệ thống tệp và giải nén nó ở đó. Tôi sẽ cập nhật câu trả lời của tôi để chứng minh.
rdlowrey

Nếu bạn không có lớp ZipArchive thì sao? Tôi đang làm việc trên một trang web có lưu trữ tào lao và tôi gặp Fatal error: Class 'ZipArchive' not foundlỗi khi thử tập lệnh này :-( Có lựa chọn nào vào thời điểm đó không?
CWSpear

2
@CWSpear bạn sẽ cầnzlib thư viện cơ bản để thực hiện khá nhiều hoạt động nén / giải nén với PHP. Ngay cả để thực hiện các cuộc gọi hệ thống, bạn cần phải có thư viện cơ bản. Đây là một điều rất phổ biến mặc dù, và không có nó là ngoại lệ. Nếu bạn đang chia sẻ lưu trữ, họ nên cài đặt nó cho bạn.
Mặt

Vâng, đó là lưu trữ khá rẻ như tôi đã nói. Dù sao, cảm ơn vì đã trả lời, đó là điều tốt để biết.
CWSpear

38

Xin vui lòng, đừng làm như vậy (vượt qua GET var để trở thành một phần của cuộc gọi hệ thống). Sử dụng ZipArchive thay thế.

Vì vậy, mã của bạn sẽ giống như:

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

Và để trả lời câu hỏi của bạn, lỗi của bạn là 'cái gì đó $ var cái gì khác' phải là "cái gì đó $ var cái gì khác" (trong dấu ngoặc kép).


3
Rất tiếc, xin lỗi vì đã xử lý về cơ bản cùng một câu trả lời năm phút sau. Không thấy bạn ở đó :)
rdlowrey

10

Sử dụng getcwd()để giải nén trong cùng thư mục

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

5

Đơn giản chỉ cần thử yourDestinationDir là đích để trích xuất hoặc xóa -d yourDestinationDir để giải nén vào thư mục gốc.

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

1
Tôi đã từng yourDestinationDirsession_save_path() . DIRECTORY_SEPARATOR . "$name" . DIRECTORY_SEPARATOR nơi $namelà thư mục đích để giải nén trong thư mục phiên.
Ramratan Gupta

1
Hãy thực sự cẩn thận khi xử lý các hàm hệ thống hoặc exec có chứa các biến! Nó có thể đưa ra một dòng lệnh miễn phí từ máy chủ của bạn cho một hacker.
Maxime

@maxime Làm thế nào là có thể? hãy giải thích vì tôi nghĩ php là biện pháp để ngăn chặn điều đó xảy ra. Quay lại yêu cầu của bạn với sự thật
Samuel Kwame Antwi

@SamuelKwameAntwi exec và system đang gọi shell hệ thống, với người dùng php. Vì vậy, nếu người dùng của bạn là www, bạn có thể thực hiện tất cả những gì người dùng unix "www" có thể làm trên dòng lệnh, bao gồm xóa tệp hoặc thư mục. Thật tồi tệ nếu người dùng php của bạn đã root. Bạn có thể tìm thêm thông tin về nó ở đó: stackoverflow.com/questions/3115559/Exloitable-php-fifts
maxime

5

Tôi đã cập nhật câu trả lời của @rdlowrey thành một mã sạch hơn và tốt hơn, Điều này sẽ giải nén một tệp vào thư mục hiện tại bằng cách sử dụng __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 có lớp inbuilt riêng có thể được sử dụng để giải nén hoặc trích xuất nội dung từ tệp zip. Lớp học là ZipArchive. Dưới đây là mã PHP đơn giản và cơ bản sẽ trích xuất một tệp zip và đặt nó vào một thư mục cụ thể:

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

Nếu bạn muốn một số tính năng nâng cao thì bên dưới là mã được cải tiến sẽ kiểm tra xem tệp zip có tồn tại hay không:

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

Nguồn: Làm thế nào để giải nén hoặc giải nén các tệp zip trong PHP?


0

Tôi đã cập nhật câu trả lời của Morteza Ziaeemehr thành một mã sạch hơn và tốt hơn, Điều này sẽ giải nén một tệp được cung cấp trong biểu mẫu vào thư mục hiện tại bằng cách sử dụng 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

Chỉ là sự thay đổi

system('unzip $master.zip');

Để cái này

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

hoặc cái này

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


6
Trong khi điều này có thể khắc phục vấn đề anh ta đang gặp phải, hãy xem các câu trả lời khác để xem tại sao đây là lời khuyên tồi.
rjdown

0

bạn có thể sử dụng chức năng đóng gói sẵn

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

Làm thế nào để sử dụng nó.

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

0

Sử dụng bên dưới mã PHP, với tên tệp trong "tên" param param

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

Hàm PHP đơn giản để giải nén. Vui lòng đảm bảo rằng bạn đã cài đặt tiện ích mở rộng zip trên máy chủ của mình.

/**
 * 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

Chỉ cần sử dụng này:

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

trong mã của bạn $masterđược truyền dưới dạng một chuỗi, hệ thống sẽ tìm kiếm một tệp có tên$master.zip

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

5
Hoàn toàn sai. 'unzip' $mastersẽ không hoạt động trừ khi bạn thêm một khoảng trắng sau khi giải nén và thêm một khoảng thời gian sau một trích dẫn. Sẽ dễ dàng hơn nhiều để đề xuất system("unzip $master.zip")với dấu ngoặc kép, hoặc ít nhất là một câu trả lời hợp lệ.
Nicholas Blasgen

1
Sử dụng các chức năng hệ thống PHP tốt hơn là dựa vào các chức năng hệ thống.
Sloan Thrasher

Như đã nhấn mạnh trong câu trả lời được chấp nhận - vui lòng vệ sinh đầu vào của người dùng, bất kỳ ai cũng có thể thêm bất cứ điều gì vào $_GETchuỗi truy vấn này và đưa mã của riêng họ vào systemcuộc gọi
jg2703
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.