แตกไฟล์ด้วย php


198

ฉันต้องการคลายซิปไฟล์และใช้งานได้ดี

system('unzip File.zip');

แต่ฉันต้องส่งชื่อไฟล์ผ่าน URL และไม่สามารถใช้งานได้นี่คือสิ่งที่ฉันมี

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

ฉันกำลังคิดถึงอะไร ฉันรู้ว่ามันจะต้องเป็นสิ่งที่เล็กและโง่ฉันกำลังมองเห็น

ขอบคุณ,


35
เครื่องหมายคำพูดคู่ประเมินตัวแปร คำพูดเดียวไม่ได้ แต่ระวังให้ดีเพราะการส่งอินพุตไปยังการเรียกของระบบอาจเป็นอันตรายได้
Wiseguy

25
ต้องบอกว่าฉันไม่ชอบน้ำเสียงที่เป็นศัตรูของความคิดเห็นบางอย่าง หากพวกคุณรู้ว่าเธอกำลังหลงทางอยู่ให้บอกเรื่องนี้กับเขา เราทุกคนคิดถึงบางอย่างในบางจุด
เซบาสเตียนมัค

ข้อผิดพลาดที่นี่เป็นเรื่องง่าย คุณกำลังพยายามใช้การแก้ไขสตริงด้วยเครื่องหมายคำพูดง่าย ๆ แทนที่จะเป็นเครื่องหมายคำพูดคู่ การแก้ไขสตริงไม่ทำงานกับอัญประกาศอย่างง่ายเพราะมันใช้สำหรับตัวอักษรสตริง ดังนั้นการเปลี่ยนรหัสของคุณsystem("unzip $master.zip");ควรจะทำงาน
Asier Paz

คำตอบ:


500

ฉันคิดว่ารหัสของคุณมาจากการสอนออนไลน์ที่ไหนสักแห่ง? ในกรณีดังกล่าวงานที่ดีพยายามที่จะคิดออกเอง ในทางกลับกันความจริงที่ว่ารหัสนี้สามารถเผยแพร่ทางออนไลน์ได้ที่ไหนสักแห่งเป็นวิธีที่ถูกต้องในการคลายซิปไฟล์เป็นเรื่องที่น่ากลัวเล็กน้อย

PHP มีส่วนเสริมในตัวสำหรับจัดการกับไฟล์บีบอัด ไม่จำเป็นต้องใช้systemสายสำหรับสิ่งนี้ ZipArchiveเอกสารเป็นตัวเลือกหนึ่ง

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

นอกจากนี้ตามที่คนอื่น ๆ ได้แสดงความคิดเห็น$HTTP_GET_VARSได้ถูกคัดค้านตั้งแต่รุ่น 4.1 ... ซึ่งเป็นเวลานานในการ reeeeeally ที่ผ่านมา อย่าใช้มัน ใช้$_GETsuperglobal แทน

สุดท้ายให้ระวังอย่างมากเกี่ยวกับการยอมรับอินพุตใดก็ตามที่ส่งผ่านไปยังสคริปต์ผ่าน$_GETตัวแปร

ป้อนผู้ใช้ให้สะอาดอยู่เสมอ


UPDATE

ตามความคิดเห็นของคุณวิธีที่ดีที่สุดในการแตกไฟล์ zip ลงในไดเรกทอรีเดียวกันที่อยู่นั้นคือการกำหนดเส้นทางฮาร์ดไปยังไฟล์และแยกไฟล์ไปยังตำแหน่งนั้นโดยเฉพาะ ดังนั้นคุณสามารถทำได้:

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

ขอบคุณสำหรับคำแนะนำ ฉันยังใหม่กับสิ่งนี้และแค่หาทุกอย่างออกมา ด้วยรหัสของคุณฉันจะเอามันไปแตกซิปในโฟลเดอร์เดียวกันกับไฟล์ซิปได้อย่างไร?
BostonBB

2
ดีมีความแตกต่างระหว่างไดเรกทอรีการทำงานปัจจุบันของสคริปต์ของคุณและไดเรกทอรีที่ไฟล์ซิปอยู่ หากไฟล์ zip อยู่ในไดเรกทอรีเดียวกับสคริปต์ที่คุณสามารถทำได้$zip->extractTo('./');อย่างไรก็ตามอาจเป็นกรณีนี้ไม่ได้ ตัวเลือกที่ดีกว่าคือการกำหนดตำแหน่งของไฟล์ zip ในระบบไฟล์และแตกไฟล์นั้น ฉันจะอัปเดตคำตอบเพื่อสาธิต
rdlowrey

ถ้าคุณไม่มีคลาส ZipArchive ให้ใช้งาน ฉันทำงานในไซต์ที่มี crap hosting และฉันได้รับFatal error: Class 'ZipArchive' not foundข้อผิดพลาดซึ่งฉันลองใช้สคริปต์นี้ :-( มีตัวเลือกใด ๆ ณ จุดนั้นหรือไม่
CWSpear

2
@CWSpear คุณจะต้องใช้zlibไลบรารีพื้นฐานเพื่อดำเนินการบีบอัด / คลายการบีบอัดด้วย PHP แม้แต่การโทรออกด้วยระบบคุณต้องมีไลบรารี่พื้นฐาน แม้ว่านี่จะเป็นสิ่งที่แพร่หลายมาก แต่ก็ไม่มีข้อยกเว้น หากคุณอยู่ในพื้นที่สาธารณะพวกเขาควรติดตั้งให้คุณ มิฉะนั้นเพียงแค่ google บางอย่างเช่น "วิธีการติดตั้งฟังก์ชั่น Zip รองรับ PHP"
rdlowrey

ใช่มันเป็นโฮสติ้งราคาถูกสวยอย่างที่ฉันบอก อย่างไรก็ตามขอบคุณสำหรับการตอบกลับเป็นสิ่งที่ดีที่จะรู้
CWSpear

38

โปรดอย่าทำอย่างนั้น (ผ่าน GET var เพื่อเป็นส่วนหนึ่งของการเรียกระบบ) ใช้ZipArchiveแทน

ดังนั้นรหัสของคุณควรมีลักษณะดังนี้:

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

และเพื่อตอบคำถามของคุณข้อผิดพลาดของคุณคือ 'สิ่งที่ $ var อย่างอื่น' ควรเป็น "สิ่งที่ $ var อย่างอื่น" (ในเครื่องหมายคำพูดคู่)


3
+1 โอ๊ะโอขออภัยในการแก้ปัญหาโดยทั่วไปคำตอบเดียวกันนี้ในอีกห้านาที ไม่เห็นคุณที่นั่น :)
rdlowrey

10

ใช้getcwd()เพื่อแยกในไดเรกทอรีเดียวกัน

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

5

ลองใช้yourDestinationDirนี้เป็นปลายทางในการแยกหรือลบ-d yourDestinationDirเพื่อแยกไปยัง root dir

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

1
ผมเคยyourDestinationDirเป็นsession_save_path() . DIRECTORY_SEPARATOR . "$name" . DIRECTORY_SEPARATOR ที่$nameเป็นโฟลเดอร์เป้าหมายที่จะเปิดเครื่องรูดในโฟลเดอร์เซสชั่น
Ramratan Gupta

1
ระวังให้มากเมื่อจัดการกับระบบหรือฟังก์ชั่น exec ซึ่งมีตัวแปร! มันสามารถปล่อยให้บรรทัดคำสั่งฟรีจากเซิร์ฟเวอร์ของคุณไปยังแฮ็กเกอร์
maxime

@ maxime เป็นไปได้อย่างไร โปรดอธิบายเพราะฉันคิดว่า php เป็นมาตรการในการหยุดสิ่งนั้นไม่ให้เกิดขึ้น สำรองการอ้างสิทธิ์ของคุณด้วยข้อเท็จจริง
Samuel Kwame Antwi

@SamuelKwameAntwi exec และระบบกำลังเรียกเชลล์ระบบด้วยผู้ใช้ php ดังนั้นหากผู้ใช้ของคุณคือ www คุณสามารถทำทุกสิ่งที่ผู้ใช้ unix "www" สามารถทำได้บนบรรทัดคำสั่งรวมถึงการลบไฟล์หรือไดเรกทอรี มันเลวร้ายที่สุดถ้าผู้ใช้ php ของคุณรูต คุณสามารถหาข้อมูลเพิ่มเติมเกี่ยวกับมันได้ที่: stackoverflow.com/questions/3115559/exploitable-php-functions
maxime

5

ฉันปรับปรุงคำตอบของ@rdlowrey__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 มีคลาส inbuilt ของตัวเองที่สามารถใช้เพื่อคลายซิปหรือแยกเนื้อหาจากไฟล์ซิป คลาสคือ ZipArchive ด้านล่างเป็นรหัส PHP พื้นฐานและง่ายที่จะแยกไฟล์ zip และวางไว้ในไดเรกทอรีเฉพาะ:

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

หากคุณต้องการคุณสมบัติขั้นสูงบางส่วนด้านล่างคือรหัสที่ได้รับการปรับปรุงซึ่งจะตรวจสอบว่ามีไฟล์ซิปอยู่หรือไม่:

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

ที่มา: วิธีคลายซิปหรือแตกไฟล์ zip ใน PHP


0

ฉันคำตอบที่ได้รับการปรับปรุงMorteza Ziaeemehrเพื่อทำความสะอาดและรหัสที่ดีกว่านี้จะเปิดเครื่องรูดแฟ้มให้ภายในแบบฟอร์มลงในไดเรกทอรีปัจจุบันใช้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

เพียงแค่เปลี่ยน

system('unzip $master.zip');

ถึงสิ่งนี้

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

หรืออันนี้

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


6
ขณะนี้อาจแก้ไขปัญหาที่เขามีอยู่ดูที่คำตอบอื่น ๆ เพื่อดูว่าทำไมนี่คือคำแนะนำที่ไม่ดี
rjdown

0

คุณสามารถใช้ฟังก์ชั่นที่ถูกบรรจุล่วงหน้าได้

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

วิธีใช้งาน

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

0

ใช้ด้านล่างโค้ด PHP พร้อมชื่อไฟล์ใน URL พารามิเตอร์ "ชื่อ"

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

ฟังก์ชั่น PHP ง่ายต่อการคลายซิป โปรดตรวจสอบว่าคุณติดตั้งส่วนขยาย zip บนเซิร์ฟเวอร์ของคุณ

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

เพียงใช้สิ่งนี้:

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

ในรหัสของคุณ$masterจะถูกส่งเป็นสตริงระบบจะค้นหาไฟล์ที่เรียกว่า$master.zip

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

5
ผิดอย่างสมบูรณ์ 'unzip' $masterจะไม่ทำงานจนกว่าคุณจะเพิ่มช่องว่างหลังจากคลายซิปและเพิ่มจุดหลังจากคำพูดเดียว จะเป็นการง่ายกว่าที่จะแนะนำsystem("unzip $master.zip")ด้วยเครื่องหมายคำพูดคู่หรืออย่างน้อยคำตอบที่ถูกต้อง
Nicholas Blasgen

1
การใช้ฟังก์ชั่นระบบ PHP ดีกว่าการใช้ฟังก์ชั่นระบบ
สโลน Thrasher

ดังที่เน้นในคำตอบที่ได้รับการยอมรับ - โปรด sanitize การป้อนข้อมูลของผู้ใช้ทุกคนสามารถเพิ่มสิ่งใด ๆ ใน$_GETสตริงการสืบค้นนี้และฉีดรหัสของตัวเองลงในการsystemโทร
jg2703
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.