[hello world 動かない ][検索]

プログラミング関連で自分が調べた事をメモる

cakephp zip 作成 ダウンロード

CakePHPでZIPファイルをダウンロードする


PHP:5.6.3
CakePHP: 2.6.4

主にこのクラスを使って処理をするのだけど
PHP: ZipArchive - Manual

ZipArchiveにディレクトリをzipに含めるというメソッドがない。
ディレクトリを指定して、中身を全部追加したい場合は、
空のディレクトリを作るメソッドと、ファイルを追加するというメソッドを組み合わせて
処理を作る必要がある。


<?php

class DownloadController extends AppController {
  public function zip() {
    $zip = new ZipArchive();
    $zip_dir_path = TMP;
    $zip_file_name = $this->Session->id().'.zip';

    if (!$zip->open($zip_dir_path.$zip_file_name, ZipArchive::CREATE | ZIPARCHIVE::OVERWRITE)) {
      throw new InternalErrorException();
    }

    // 文字列をファイルにしてzipに追加する場合
    if (!$zip->addFromString('string.txt', '文字列をファイルにして追加')) {
      throw new InternalErrorException();
    }

    // ファイルをzipに追加する場合
    if (!$zip->addFile(TMP.'kinoko.jpg', 'image.jpg')) {
      throw new InternalErrorException();
    }

    // ディレクトリの中を全てzipに追加する場合
    $this->addDirectoryToZip($zip, TMP.'dirname');

    $zip->close();

    $this->autoRender = false;
    $this->response->type('application/zip');
    $this->response->file($zip_dir_path.$zip_file_name, array('download' => true));
    $this->response->download('test2.zip');
  }

  // ファイル名一覧を取得する
  private function getFiles($dir_path) {
    $files = array();
    if(is_dir($dir_path)) {
      $dh = opendir($dir_path);
      while($file = readdir($dh)) {
        if ($file != '.' && $file != '..') {
          array_push($files, $file);
        }
      }
      closedir($dh);
    }
    var_dump($files);
    return $files;
  }


  // ディレクトリをzipに追加する
  private function addDirectoryToZip($zip, $src_dir_path, $tar_dir_path = '') {
    // zip 内にディレクトリを作成する
    if (strlen($tar_dir_path) > 0) {
      if (!$zip->addEmptyDir($tar_dir_path)) {
        throw new InternalErrorException();
      }
    }

    // ディレクトリ内のファイルを取得する
    foreach ($this->getFiles($src_dir_path) as $file) {
      $src_file_path = $src_dir_path.'/'.$file;
      $tar_file_path = strlen($tar_dir_path) > 0 ? $tar_dir_path.'/'.$file : $file;

      if (is_dir($src_file_path)) {
        // ディレクトリの場合、中のファイルをzipに追加する
        $this->addDirectoryToZip($zip, $src_file_path, $tar_file_path);
      } else {
        // ファイルをzipに追加する
        if(!$zip->addFile($src_file_path, $tar_file_path)) {
          throw new InternalErrorException();
        }
      }
    }
  }
}

CakePHPの方は

$this->autoRender = false;
$this->response->type('application/zip');
$this->response->file($zip_dir_path.$zip_file_name, array('download' => true));
$this->response->download('test2.zip');

Viewを使用しない
Responseがzipであること宣言する
Responseにzipファイルを追加する
ダウンロードさせるファイル名を設定する

という感じで設定しているらしい。

zipを作成するディレクトリとか、削除するタイミングとかを別途考えないといけない。