cakePHPにてCSVのダウンロードなんぞを。
以前このエントリーでCSVダウンロードに関しては取り扱ったのですが、
- ボタンを押す
- ファイルダイアログが開く
- パスを選ぶ
- 意図したデータを正常にダウンロードさせる
この一連の流れを実装するのがなかなか大変でした。
下記のソースで無事にダウンロードできたので、参考になれば幸いです
メインのCSVダウンロードメソッド
1 2 3 4 5 6 7 8 9 10 11 12 |
$this->autoRender=false; $downloadData = array(); $downloadData = $this->Model->ダウンロードデータの多次元連想配列を取り出すメソッド; $bodyData = $this->Model->exportCSV ( $downloadData ); $csvFileName="sample.csv" // アクセスした時にダウンロードさせる為のヘッダを設定します。 header ("Content-disposition: attachment; filename=" . $csvFileName); header ("Content-type: application/octet-stream; name=" . $csvFileName); // バッファを出力して完成です。 print($bodyData); //exitをいれておかないとhtmlのソースを含んだCSVファイルになってしまうので注意です。 exit; |
exportCSVは以前紹介したエントリーのCsvExportBehaviorの中のメソッドです。
そのままだとデータの受け渡しができないので若干カスタマイズをします。
少しカスタマイズしたCsvExportBehavior.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
<?php /** * Copyright 2011-2012, PRONIQUE Softeare (http://pronique.com) * * Licensed under The MIT License * Redistributions of files must retain the above copyright notice. * * @copyright Copyright 2011-2012, PRONIQUE Software (http://pronique.com) * @license MIT License (http://www.opensource.org/licenses/mit-license.php) */ /** * ProUtils Plugin * * ProUtils Csv Import Behavior * * @package ProUtils * @subpackage ProUtils.Model.Behavior */ class CsvExportBehavior extends ModelBehavior { /** * Exportable behavior settings * * @var array */ public $settings = array(); /** * List of errors generated by the export action * * @var array */ public $errors = array(); /** * List of objects instances or callables to notify from events on this class * * @var array */ protected $_subscribers = array(); protected $tmpDir = 'csvexport'; /** * Initializes this behavior for the model $Model * * @param Model $Model * @param array $settigs list of settings to be used for this model * @return void */ public function setup(Model $Model, $settings = array()) { if (!isset($this->settings[$Model->alias])) { $this->settings[$Model->alias] = array( 'encoding' => 'utf8', 'delimiter' => ',', 'enclosure' => '"', 'max_execution_time' => 360 ); } $this->settings[$Model->alias] = array_merge($this->settings[$Model->alias], $settings); } /** * Returns a csv formatted string of every record in the model * * @param Model $Model * @return string the csv data */ public function exportCSV(Model &$Model, $customizeData = array() ) { if( !ini_get('safe_mode') && ini_get('max_execution_time') < $this->settings[$Model->alias]['max_execution_time'] ){ set_time_limit($this->settings[$Model->alias]['max_execution_time']); //Extend timout to 6 minutes for large data exports. } $Model->recursive = -1; if( empty($customizeData)){ $records = $Model->find('all'); }else{ $records = $customizeData; } if ( !empty($records ) ) { $this->ensureTmp(); $tmpFilename = TMP . $this->tmpDir . DS . strtolower( Inflector::pluralize($Model->alias) ) . '-' . date('Ymd-Hms') . '.csv'; $fp = fopen($tmpFilename, 'w'); if ( $this->settings[$Model->alias]['encoding'] == 'utf8' ) { fwrite($fp, "\xEF\xBB\xBF"); fputcsv( $fp, $this->arrayToUtf8( array_keys($records[0][$Model->alias]) ), $this->settings[$Model->alias]['delimiter'], $this->settings[$Model->alias]['enclosure'] ); } else { fputcsv( $fp, array_keys($records[0][$Model->alias]), $this->settings[$Model->alias]['delimiter'], $this->settings[$Model->alias]['enclosure'] ); } foreach( $records as $record ) { if ( $this->settings[$Model->alias]['encoding'] == 'utf8' ) { fputcsv($fp, $this->arrayToUtf8( $record[$Model->alias] ), $this->settings[$Model->alias]['delimiter'], $this->settings[$Model->alias]['enclosure'] ); } else { fputcsv($fp, $record[$Model->alias], $this->settings[$Model->alias]['delimiter'], $this->settings[$Model->alias]['enclosure'] ); } } fclose( $fp ); $data = file_get_contents( $tmpFilename ); $this->cleanupTmp( $tmpFilename ); return $data; } return false; } /** * Returns the errors generated by last export * * @param Model $Model * @return array */ public function getExportErrors(Model &$Model) { if (empty($this->errors[$Model->alias])) { return array(); } return $this->errors[$Model->alias]; } /** * Attachs a new listener for the events generated by this class * * @param Model $Model * @param mixed listener instances of an object or valid php callback * @return void */ public function attachExportListener(Model $Model, $listener) { $this->_subscribers[$Model->alias][] = $listener; } /** * Notifies the listeners of events generated by this class * * @param Model $Model * @param string $action the name of the event. It will be used as method name for object listeners * @param mixed $data additional information to pass to the listener callback * @return void */ protected function _notify(Model $Model, $action, $data = null) { if (empty($this->_subscribers[$Model->alias])) { return; } foreach ($this->_subscribers[$Model->alias] as $object) { if (method_exists($object, $action)) { $object->{$action}($data); } if (is_callable($object)) { call_user_func($object, $action, $data); } } } /** * This Behavior writes tmp files to take advantage of the built-in fputcsv function. * */ protected function ensureTmp() { $tmpDir = TMP . $this->tmpDir; if ( !file_exists($tmpDir ) ) { mkdir( $tmpDir, 0777); } } /** * Delete the tmp file, only if $tmp_file lives in TMP directory * otherwise throw an Exception * * @param mixed $tmp_file */ protected function cleanupTmp( $tmp_file='' ) { $realpath = realpath( $tmp_file ); if ( substr( $realpath, 0, strlen( TMP ) ) != TMP ) { throw new Exception('I refuse to delete a file outside of ' . TMP ); } if ( file_exists( $tmp_file ) ) { unlink( $tmp_file ); } } /** * if array is not UTF-8 then convert keys and values to UTF-8 * method is recursive * * @param mixed $in */ protected function arrayToUtf8($in) { if (is_array($in)) { foreach ($in as $key => $value) { $out[$this->arrayToUtf8($key)] = $this->arrayToUtf8($value); } } elseif(is_string($in)) { if(mb_detect_encoding($in) != "UTF-8") return utf8_encode($in); else return $in; } else { return $in; } return $out; } } |
参考リンク