2011-12-28 12 views
1

この関数は結果セット(ファイル名)を返し、ユーザーがデスクトップに保存するためにそれらを圧縮します。千以上のファイルを解凍することができません

function getFiles() { 
error_reporting(E_ALL); 
ini_set("display_errors", 1); 
ini_set('zlib.output_compression', 'Off'); 
$result = null; 
$ZIPresult = null; 
$cleanup = null; 
$output = null; 
$fileName = 'SearchResult.zip'; 
//remove old zip if any 
$cleanup = shell_exec("/bin/rm -f SearchResult.zip"); 
error_log("SHELL OUTPUT=>" . $cleanup, 0); 
//test 
if (empty($_POST['DBSite'])) { return null; } 
$mydir = MYDIR; // set from the CONSTANT 
$dir = opendir($mydir); 
$DBSite = $_POST['DBSite']; 
$getfilename = mysql_query("select /*! SQL_CACHE */ filename from automation_search where site='" . $DBSite . "'") or die(mysql_error()); 
while ($row = mysql_fetch_array($getfilename)) { 
$filename = $row['filename']; 
$result .= '<tr><td><a href="' . basename($mydir) . '/' . $filename . '" target="_blank">' . $filename . '</a></td></tr>'; 
$ZIPresult .= basename($mydir) . '/' . escapeshellarg($filename).' '; 
} 

if ($result) { 
$result = "<table><tbody><tr><td>Search Results.</td></tr> $result</table>"; 
$output = shell_exec("/usr/bin/zip -R SearchResult.zip ". $ZIPresult ." 2>&1 "); 
error_log("SHELL OUTPUT=>" . $output, 0); 
error_log("ZIP FILENAME=>" . $fileName, 0); 

if (file_exists($fileName)) { 
//header for forced download 
    header('Content-Description: File Transfer'); 
    header('Content-Type: application/octet-stream'); 
    header('Content-Disposition: attachment; filename='.basename($fileName)); 
    header('Content-Transfer-Encoding: binary'); 
    header('Expires: 0'); 
    header('Cache-Control: must-revalidate'); 
    header('Pragma: public'); 
    header('Content-Length: ' . filesize($fileName)); 
    ob_clean(); 
    flush(); 
    readfile($fileName); 
    exit; 
    } 
} 

return $result; 
} 

これは、1,000ファイル(約)未満でのみ動作します。あたかもメモリの限界に達していて、ファイルのリストがスクリーンに出力されているかのようです。

エラーがError.logです。 ZIPファイルには、私が

shell_exec("/usr/bin/zip -R SearchResult.zip ". $ZIPresult ." 2>&1 ");

ませ差に

shell_exec("/usr/bin/zip SearchResult.zip ". $ZIPresult ." ");から私のZIPのコマンドラインを変更してみました作成されていません。私は何が欠けていますか?

+0

SQL引数もエスケープするように注意してください。 '$ _POST ['DBSite']'。 – hakre

+0

zipの 'shell_exec'が機能しない場合(戻り値を厳密にチェックし、関数のマニュアルページと比較してください)、引数が多すぎる問題に遭遇するかもしれません。引数にファイルのリストを渡す代わりに ' - @'を使い、1行に1ファイルずつSTDINでファイルを渡すことができます。 – hakre

答えて

3

コマンドライン引数に許可される最大文字数が当てはまる可能性があります。 PHPのbuilt-in ZIP-supportを使いたいと思うかもしれません。

そして、サイドノートで:あなたのスクリプトは、ユーザーの入力を受け付けている場合、あなたはおそらくそれを脱出したいと思います。割り当て$DBSite = $_POST['DBSite']は、mysql_real_escape_string()を使用する必要があります。


EDIT:

ZIPバイナリへのOpen a pipe[email protected]オプションを渡す:ZipArchiveので、あなたが考えることができます別のオプションがあり、使用できません。これにより、ファイル名はSTDINから読み取られます。このパイプに含めるファイル名を書き込むことができます。

$p = popen('/usr/bin/zip [email protected] -R SearchResults.zip', 'w'); 

foreach ($files as $filename) 
    fwrite($p, $filename . "\n"); 
pclose($p); // Important. Handle needs to be closed with pclose() 
+0

新しいZipArchive()ライブラリ/クラスは本番環境では使用できないため、代わりにUnixユーティリティZIPを使用することにしました。 – Chris

+0

'popen'を使ってこのトリックを行いました。ありがとうございました。受け入れられ、投票された。 – Chris

1

あなたは、おそらく(私は正確に把握していないが、それはいくつかの千文字でなければなりません)、コマンド・ライン・サイズの制限に達しています。

いくつかのものにあなたのタスクを分割:まず、ファイルのカップルの何百ものzipファイルを作成し、既存のzipファイルに追加するには、より多くのコマンドを発行します。

関連する問題