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

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

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

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

PHP

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

Q&A

解決済

1回答

7184閲覧

サーバのtempフォルダを介さず複数のCSVファイルを出力させるには

JavaPHP-nosnos

総合スコア29

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

PHP

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

0グッド

0クリップ

投稿2015/11/10 07:38

編集2015/11/10 09:29

はじめて質問させていただきます。

PHP5.3.3で、以下の問題で悩んでいます。

ZIPファイルの中に3つのCSVが入っているという形で、
CSV形式のデータをファイル出力させたいと思っています。

実行すると、それがサーバ上の\temp のフォルダに出てしまうのですが、
そこには出さずに、このソースにアクセスしたクライアント側でだけ
出力が行われるようにしたいのです。しかしそのようにできません。

【手順】
①3つの配列変数をfputs()でサーバに書き込みます。
②ZipArchiveクラスのオブジェクトを作成します。
③header()でダウンロードダイアログを開きファイル出力を行います。

※②③についてはソースは以下のようになっています。

php

1 $category = array(1 => 'ステートメント', 2 => 'ポジション', 3 => '全口座'); 2 $csv_filename1 = 'temp/'."$str_csv_subject_sub".'('."$category[1]".')'.'.csv'; 3 $csv_filename2 = 'temp/'."$str_csv_subject_sub".'('."$category[2]".')'.'.csv'; 4 $csv_filename3 = 'temp/'."$str_csv_subject_sub".'('."$category[3]".')'.'.csv'; 5 $files = array(mb_convert_encoding($csv_filename1,"SJIS-win","UTF-8"), mb_convert_encoding($csv_filename2,"SJIS-win","UTF-8"), mb_convert_encoding($csv_filename3,"SJIS-win","UTF-8")); 6 $zip_filename = 'temp/'."$str_csv_subject_sub".'.zip'; 7 8 //■ZipArchiveクラスの使用■ 9 $zip = new ZipArchive(); 10 $res = $zip->open("$zip_filename", ZipArchive::CREATE); 11 12 if($res === true) 13 { 14 foreach($files as $file) 15 { 16 $zip->addFile($file); 17 } 18 $zip->close(); 19 } 20 else 21 { 22 echo 'Error Code: ' . $res; 23 } 24 25 //■ZIPファイル出力ウィンドウ表示■ 26 $file = $zip_filename; 27 28 header('Content-Type: application/octet-stream'); 29 header(sprintf('Content-Disposition: attachment; filename="%s"', basename($file)) ); 30 header(sprintf('Content-Length: %d', filesize($file)) ); 31 readfile($file);

すると、このindex.php のソースの直下の\temp のフォルダの中に
ZIPファイル1つとCSVファイル3つが出力されます。

$csv_filename1~3 や$zip_filename の先頭の'temp/'を外しても、
同じ場所、\temp のフォルダの中に出てきます。

解決案として、配列変数をサーバに書き込まず、
直接CSVファイルとしてダウンロードするという方法が可能です。

しかし、HTTPレスポンスはサーバからクライアントに
1回しか返せないため、「3つの」CSVファイルを出力できません。
その方法だと1つのファイルしか出力できません。

どうすれば、クライアント側だけに、3つのCSVファイルを出力できるでしょうか。

私の基本的な理解が不足しているところがありましたらすみません。

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

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

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

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

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

guest

回答1

0

ベストアンサー

tempファイルに出力されることによって何が困るか次第ですが、
・残ってしまって困る
・クライアントからアクセスされて困る
というような理由であれば以下のアプローチになるかと思います。

①3つの配列変数をfputs()でサーバに書き込みます。
+ファイルは他からは読み込みも出来ないようにロックします。
+ドキュメントルート以下には生成され無いようにするか、.htaccessなどでクライアントがアクセス出来ないことを保証する
②ZipArchiveクラスのオブジェクトを作成します。
③header()でダウンロードダイアログを開きファイル出力を行います。
④一時ファイルを削除します

投稿2015/11/10 07:47

tanat

総合スコア18706

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

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

JavaPHP-nosnos

2015/11/10 07:53

回答の早さに驚愕しています。どうもありがとうございます!!! 私自身がサーバの設定をいじる権限がないのと、やっぱりtempフォルダ内への生成自体が行われないようにしたいという要望なのですが、大変参考になりました!!!
tanat

2015/11/10 08:12

tempファイルを使わない場合、全てをメモリに格納しなければならなくなってしまうので、汎用性と実用性の面で問題が出るんだと思います。 特にwebアプリケーションだと1リクエストに多くのメモリを割けないはずなので。。。
JavaPHP-nosnos

2015/11/10 08:15

そうなのですか……いろいろありがとうございます!!!
tanat

2015/11/10 08:27

確認してみたら、一応出来るような感じはあります。 http://php.net/manual/ja/ziparchive.addfromstring.php あらかじめzipファイルを作って、それに読み込んだ内容を追加していく形ですね。 この場合でtempファイルが出来ないかは試していませんが、ご要望通りの挙動になるかもしれません。
JavaPHP-nosnos

2015/11/10 09:05

ありがとうございます、いただいた指針を元にソースを書いてみたいと思います(心許ないですが)。またコメントさせてください!!!
JavaPHP-nosnos

2015/11/11 06:23

addFromString()の挙動を見るために、以下のような単純な置き換えをしたところ、やはりサーバのtemp フォルダにいつもどおりにファイルが出てきてしまいます(中身が「test」となる)。 それをもって、addFromString()の使用では解決できないということになりますでしょうか。 旧) $zip->addFile($file); 改) $zip->addFromString($file,’test’);
JavaPHP-nosnos

2015/11/11 08:11

それか、HTTPレスポンスを3回返す方法なんてないのでしょうか。
tanat

2015/11/11 08:52

うーん、3回返そうと思ったら、アクセスする方が3回アクセスする必要があるので、ダウンロードするページでjavascriptを使って非同期で3回別々のリクエストを出せば可能な気もします。 ただ、「やっぱりtempフォルダ内への生成自体が行われないようにしたいという」という要望が他の要件、 例えばこの場合は既に確立されている手法を使わないことによるバグの発生リスクが高くなることが予想されるわけですが、品質を確保することより優先度が高いのでしょうか? 「やっぱりtempフォルダ内への生成自体が行われないようにしたいという」の理由と優先度を明確にしない限りは解決に至らないと思うのが正直な感想です。
JavaPHP-nosnos

2015/11/11 09:24

サーバ管理者からすると、サーバ内のtempフォルダの中にファイルができるということは、その分メモリを圧迫しますし、不必要なファイルを手動で消していく手間が発生するので、避けられるなら避けたい、ということだと思います。 目下javascript の素養がないのですが、javascript でリクエストを3回出す、という方法でいけそうならやってみたいので、javascript の文法のチェックから始めたいと思います(笑)。
tanat

2015/11/11 09:34

であれば、作成完了後にスクリプト内で消してしまえばいいのでは?そのスクリプトがファイル作成出来る権限のあるディレクトリなので、削除も出来るはずですよ。
JavaPHP-nosnos

2015/11/12 08:44

おっしゃるように、unlink()でサーバ内にできたファイルを消すことで解決しました。 ちなみにその際、ZIPファイルは簡単に消せたのですが、CSVファイルは消せませんでした。それはファイル名を指定するところで、ファイル名を示す文字列を、mb_convert_encoding()でUTF-8からSJISに変更することで解決しました。 長きにわたっておつきあいくださりありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.51%

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

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

質問する

関連した質問