detail
/ category : php / date : 2013  » reset
zip圧縮でメモリが足りないときメモ zip.lib.phpを利用して、サーバ上で複数ファイルをzip圧縮して保存するというようなことをしていたら、エラーがでてしまって悩んだりでしたので、また同じようなときに悩まないようにメモしておく。

$file_array = array('1.jpg', '2.jpg', '3.jpg', … '100.jpg');

$zipfile = new zipfile();

foreach ($file_array as $val) {
$handle = fopen($val, "rb");
$contents = fread($handle, filesize($val));
fclose($handle);
$zipfile -> addFile($contents, $val);
}

$zip_buffer = $zipfile->file();

$filename = 'images.zip';
$handle = fopen($filename, "wb");
fwrite($handle, $zip_buffer);
fclose($handle);
こんな感じで画像名が入っている$file_arrayから、ひとつずつ読み込んで変数にセットしていき、最後にファイルに書き出して終わりというものだったのだけど、ここでまさかのメモリ不足に。。。
そもそも一つ一つの画像のサイズが大きいのと、画像点数がやたらと多いので、それらをそのまま読み込んでいけばメモリが足りなくなるのは当然。しかもこのサーバで使えるメモリが少ないということもあったり。

で、どうしたものかな~と、zip.lib.phpを覗いてみましたらば、
var $doWrite = false;
ってなものがありまして。
通常はaddFile()ではファイルデータを配列に収納していくところが、この$doWriteがtrueだと、そのままechoでぶちまけてくれるのですよ。
それならば、ひとつずつ変数にセットするのではなく、これで直接ファイルに書き出していけばいいのでは?ということで修正したのが下記。
$file_array = array('1.jpg', '2.jpg', '3.jpg', … '100.jpg');

$zipfile = new zipfile();
// DoWriteモード
$zipfile->setDoWrite();

$filename = 'images.zip';

$fp = fopen($filename, 'wb');

foreach ($file_array as $val) {
$handle = fopen($val, "rb");
$contents = fread($handle, filesize($val));
fclose($handle);
// バッファリング開始
ob_start();
$zipfile -> addFile($contents, $val);
$output = ob_get_contents();
// バッファリング終了
ob_end_clean();
fwrite($fp, $output);
}
// バッファリング開始
ob_start();
$zipfile->file();
$output = ob_get_contents();
// バッファリング終了
ob_end_clean();
fwrite($fp, $output);

fclose($fp);
とりあえずこれでメモリ不足でダウンすることなくガリガリ書き出してくれます。
ただ、ファイル数が多いとどうしても時間はかかるので、タイムアウトしないようにしておく必要はあります。
| 1 |