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このために呼び出しを使用する必要はないはずです。ZipArchivedocsは1つのオプションです。

$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から非推奨になりました... 使用しないでください。$_GET代わりにスーパーグローバルを使用してください。

最後に、$_GET変数を介してスクリプトに渡される入力を受け入れる場合は、十分に注意してください。

常にユーザー入力を無害化します。


更新

コメントのとおり、zipファイルが存在する同じディレクトリに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 2012年

2
スクリプトの現在の作業ディレクトリとzipファイルが存在するディレクトリには違いがあります。zipファイルがスクリプトと同じディレクトリに$zip->extractTo('./');ある場合は、可能ですが、そうではない可能性があります。より良いオプションは、zipファイルのファイルシステム内の場所を特定し、そこに抽出することです。答えを更新して説明します。
rdlowrey 2012年

ZipArchiveクラスを使用できない場合はどうなりますか?がらくたホスティングのあるサイトで作業していて、Fatal error: Class 'ZipArchive' not foundこのスクリプトを試すとエラーが表示されます:-(その時点でオプションはありますか?
CWSpear

2
@CWSpear では、PHPでほとんどすべての圧縮/解凍操作を実行するために、基盤となるzlibライブラリが必要になります。システムコールを行う場合でも、基盤となるライブラリが必要です。これは非常にユビキタスなことですが、それがないことは例外です。共有ホスティングを使用している場合は、インストールされます。それ以外の場合は、「PHPのZip関数のサポートをインストールする方法」などのグーグル
検索

ええ、私が言われたようにそれはかなり安いホスティングです。とにかく、返事をありがとう、それは知っておくと良いことです。
CWSpear 2012

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おっと、基本的に同じ答えを5分後に追加してすみません。そこにあなたがいなかった:)
rdlowrey '17

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を削除してルートディレクトリに抽出します。

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

1
セッションフォルダーに解凍するターゲットフォルダーの 場所yourDestinationDirとして使用しました。session_save_path() . DIRECTORY_SEPARATOR . "$name" . DIRECTORY_SEPARATOR$name
Ramratan Gupta、2016

1
変数を含むシステム関数またはexec関数を扱うときは注意してください。それはあなたのサーバーからハッカーに自由にコマンドラインを与えることができます。
maxime

@maximeそれはどのように可能ですか?私はphpがそれを防ぐための手段だと思っているので、説明してください。主張を事実で
裏付ける

@SamuelKwameAntwi execおよびsystemは、phpユーザーを使用してシステムシェルを呼び出しています。したがって、ユーザーがwwwの場合、ファイルやディレクトリの削除など、UNIXユーザー "www"がコマンドラインで実行できるすべてのことを実行できます。あなたのphpユーザーがrootである場合、それは本当に最悪です。あなたはそこでそれについてより多くの情報を見つけることができます: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には、zipファイルからコンテンツを解凍または抽出するために使用できる独自の組み込みクラスがあります。クラスはZipArchiveです。以下は、zipファイルを抽出して特定のディレクトリに配置する単純で基本的なPHPコードです。

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

いくつかの高度な機能が必要な場合は、zipファイルが存在するかどうかをチェックする改善されたコードを次に示します。

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

ソース:PHPでzipファイルを解凍または抽出する方法


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 2014年

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パラメータ "name"にファイル名を指定します

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

1
システム関数に依存するよりも、PHPシステム関数を使用する方が適切です。
スローンスラッシャー2017年

受け入れられた回答で強調したように、ユーザー入力を$_GETsystem
サニタイズ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.