質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
HTTP

HTTP(Hypertext Transfer Protocol)とはweb上でHTML等のコンテンツを交換するために使われるアプリケーション層の通信プロトコルです。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

CakePHP

CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

zip

ZIPとは、複数のファイルをひとつにまとめて圧縮したり、圧縮したファイルを展開することができるアーカイブフォーマットです。 1998年以降のWindowsOS各バージョンで、標準の圧縮フォルダとして採用されています。 MacOSでも、X v10.3以降に他の圧縮ソフトとまとめてZIP機能を採用しています。

Q&A

解決済

1回答

2928閲覧

[PHP]zipファイルのダウンロードができない

zvub1123

総合スコア230

HTTP

HTTP(Hypertext Transfer Protocol)とはweb上でHTML等のコンテンツを交換するために使われるアプリケーション層の通信プロトコルです。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

CakePHP

CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

zip

ZIPとは、複数のファイルをひとつにまとめて圧縮したり、圧縮したファイルを展開することができるアーカイブフォーマットです。 1998年以降のWindowsOS各バージョンで、標準の圧縮フォルダとして採用されています。 MacOSでも、X v10.3以降に他の圧縮ソフトとまとめてZIP機能を採用しています。

0グッド

2クリップ

投稿2020/07/22 07:19

編集2020/07/27 01:12

実現したいこと

ビューのリンククリックをトリガーに、S3バケット内に保存された複数のCSVファイルを取得し、
zipアーカイブ化してダウンロードしたいです。

実現できていること

  • 特定のPrefixを指定して、該当するキーを持つオブジェクトをapp/tmpにダウンロードする
  • ダウンロードしたファイルをzip圧縮する

という部分までは実現できています。
具体的には、app/Controller/Component/S3Component.phpにてCSVファイルのダウンロード、zip圧縮を行い、
app/controller/DownloadController.phpにてzipファイルをローカルにダウンロード、としたいのですが、
後者がうまくいかず、なぜか(おそらく該当のzipファイルが)ビュー上に文字化けした状態で表示されます。

各種バージョン情報

CakePHP : 2.10.20
PHP : 7.2.31

該当ソース群(抜粋)

  • app/Controller/Component/S3Component.php

php

1public function downloadCSVFiles($bucket, $file_path){ 2 // some settings 3 try{ 4 // download files from s3 bucket 5 $results = $client->listObjects([ 6 'Bucket' => $bucket, 7 'Prefix' => $file_path, 8 ]); 9 if (!empty($results)){ 10 $zip = new ZipArchive(); 11 if ($zip->open('tmp/test.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE) === TRUE) { 12 foreach($results['Contents'] as $result){ 13 $obj = $client->getObject([ 14 'Bucket' => $bucket, 15 'Key' => $result['Key'], 16 'SaveAs' => 'tmp/'.$result['Key'] 17 ]); 18 $zip->addFromString($result['Key'], file_get_contents('tmp/'.$result['Key'])); 19 } 20 $zip->close(); 21 } else { 22 debug('ERROR: zip open failed'); 23 } 24 }else{ 25 debug("ERROR: couldn't download csv files."); 26 } 27 } catch (S3Exception $e) { 28 debug('Error message: ' . $e->getMessage()); 29 } 30 return $zip; 31}
  • app/controller/DownloadController.php

php

1public function download($camp_id = null, $login_id = null, $file_name = null){ 2 $this->autoRender = false; 3 $bucket = Configure::read("csvExportBucketName"); 4 $zip = $this->S3->downloadCSVFiles($bucket, $camp_id.'/'.$login_id.'/'.$file_name); 5 6 if (!empty($zip)) { 7 header('Content-Disposition: attachment; filename='.$file_name.'.zip'); 8 9 $this->response->type('application/zip'); 10 $this->response->file('storage/'.$file_name.'.zip', ['download' => true]); 11 $this->response->download($file_name.'.zip'); 12 } 13}

以上となります。
おそらくController側のレスポンス作成部分がおかしいのだろうとは思っているのですが、イマイチ解決の糸口を掴めず、という状況です。
ご助力いただけると幸いです。

指摘・修正事項・不足しているソースなどあればお申しつけください。
ご回答お待ちしております。よろしくお願いします!

2020/07/27 追記★

事象としては変わらず「zipの中身が文字化けした状態でブラウザに表示されている」ままですが、
Controllerのソースを下記のように修正しました。また、debug()でresponseを出力した際のキャプチャ(文字化けzip含む)を下記に添付します。

  • app/controller/DownloadController.php修正版(1)

php

1public function download($camp_id = null, $login_id = null, $file_name = null){ 2 $this->autoRender = false; 3 $bucket = Configure::read("csvExportBucketName"); 4 $zip = $this->S3->downloadCSVFiles($bucket, $camp_id.'/'.$login_id.'/'.$file_name); 5 6 if (!empty($zip)) { 7 $file_path = WWW_ROOT.'storage'.DS.$file_name.'.zip'; 8 $this->response->type('application/zip'); 9 $this->response->type('content-Length: '.filesize($file_path)); 10 $this->response->type('Content-Disposition: attachment'); 11 $this->response->file($file_path, ['download' => true]); 12 debug($this->response); 13 } 14}
  • ブラウザの状態

レスポンスの一部とzip文字化けの一部を抜粋

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

zvub1123

2020/07/27 00:27

返信が遅くなってしまいすみません。 念のため確認しましたが、Cakeのバージョンは記載の通り「2.10.20」となります。 下記URLの通り、既知のコンテンツタイプを使用できる認識だったのですが、何か不足しているor誤っている部分があるのでしょうか。。。? https://book.cakephp.org/2/ja/controllers/request-response.html#CakeResponse::type
guest

回答1

0

自己解決

自己解決しました。

デバッグモードが有効になっていたことが原因だったようで、メソッドの冒頭でデバッグモードをOFFにする(下記ソース★部)ことによりダウンロードが可能となりました。

php

1public function download($camp_id = null, $login_id = null, $file_name = null){ 2 Configure::write('debug', 0); //<=★ 3 $this->autoRender = false; 4 $bucket = Configure::read("csvExportBucketName");

投稿2020/07/27 06:53

zvub1123

総合スコア230

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問