質問: basename($filepath); //取得ファイルをZipに追加 $zip->addFromString($filename,file_get_contents($filepath)); } $zip->close(); // ストリームに出力 header('Content-Type: application/zip; name="' . $zipFileName . '"'); header('Content-Disposition: attachment; filename="' . $zipFileName . '"'); header('Content-Length: '.filesize($zipTmpDir.$zipFileName)); echo file_get_contents($zipTmpDir.$zipFileName); // 一時ファイルを削除しておく unlink($zipTmpDir.$zipFileName); exit(); ```
回答: あなたが知らなければいけない関数やメソッドは、 ●scandir() ●is_dir() または is_file() ●ZipArchive::addEmptyDir() ●ZipArchive::addFile() です。 それらを再帰的に処理すれば、そのままのディレクトリ構造を保てますよ。 ※ユーザー関数が2つに別れてしまったので、クラスにしてあります。 ``` 0){ $this->addEmptyDir($inner_path); } // 追加するものがないならここで終了する if($item_count === 0) return true; foreach($items as $_item){ // forで行うなら$itemsは一旦array_values()を通したほうがいい $_path = $dir . DIRECTORY_SEPARATOR . $_item; $_item_inner_path = $inner_path . DIRECTORY_SEPARATOR . $_item; // ディレクトリの場合は再帰的に処理する if(\is_dir($_path)){ $_r = \call_user_func( // "$this->addDir"より保守的に好ましい [$this, __FUNCTION__], $_path, $_item_inner_path); if(!$_r) return false; } // ファイルの場合でかつ処理に失敗したときはこちら else if(!$this->addFile($_path, $_item_inner_path) && !$this->on_recursive_error($dir, $inner_path, $create_empty_dir)){ return false; } // ファイルの追加成功時は何も他には行わない } return true; } /** * 再帰的処理のときにエラーが生じたらどうするかを定義しています。 * * @param string $parent_dir ディレクトリパス * @param string $parent_inner_path zipファイル中のディレクトリパス * @param bool $create_empty_dir 空ディレクトリもディレクトリを作成するか * @return bool Falseならその場で中断 */ private function on_recursive_error($parent_dir, $parent_inner_path, $create_empty_dir){ // 自由に定義してください return false; } } /* * 下記は、質問本文のコードをちょっと改造してのテスト */ //Zipクラスロード $zip = new MyZipArchive(); //Zipファイル名指定 $zipFileName = 'test.zip'; //Zipファイル一時保存ディレクトリ取得 $zipTmpDir = '/phpdocs/filelesson'; // Zipファイルのパス $zip_file = $zipTmpDir . DIRECTORY_SEPARATOR . $zipFileName; //Zipファイルオープン $result = $zip->open($zip_file, \ZIPARCHIVE::CREATE | \ZIPARCHIVE::OVERWRITE); if ($result !== true) { return false; } //処理制限時間を外す set_time_limit(0); // ※今回の肝 $zip->addDir('/phpdocs/filelesson/images', 'images', true); // ※下記は今回処理しない while(false){ //パス $fpath_array = array('images/asn.jpg','images/asn2.jpg','images/shirika.jpg'); //Zip追加処理 foreach ($fpath_array as $filepath) { //filename取得 $filename = basename($filepath); //取得ファイルをZipに追加 $zip->addFromString($filename,file_get_contents($filepath)); } } // 処理しない範囲ここまで $zip->close(); // ストリームに出力 header('Content-Type: application/zip; name="' . $zipFileName . '"'); header('Content-Disposition: attachment; filename="' . $zipFileName . '"'); header('Content-Length: '.filesize($zip_file)); echo file_get_contents($zip_file); // 一時ファイルを削除しておく unlink($zip_file); exit(); ```