日本PHPユーザ会 掲示板

日本PHPユーザ会運営の掲示板です。※ただいまテスト運用中です。

日本PHPユーザ会 掲示板 » PHP事はじめ » HTMLの送信とファイルのダウンロードを同時にするにはどうするのですか

HTMLの送信とファイルのダウンロードを同時にするにはどうするのですか

ページ: 1

投稿者 投稿
会員
登録者: 6 2008
返信数: 5
:( 例えば、htmlのフォームで処理したいファイル名指定して、PHPファイルに送信します。
PHP側では、受取ったファイル名のファイルを読み込んで、処理した後、出力します。
このような時
function dataout($fname){
 header(attachment;filename={$_FILES['upfilename']['name']}");
 header("Content-Type: application/x-csv");
 header("Content-Length: .filesize($fname)");
 readfile($fname);
}
で、ファイルをダウンロードさせる事が出来るのですが、このfunctionで、
ダウンロードさせる前に、print文やhtmlタグで、処理内容等を表示させていると、
表示されず、全部ダウンロードするファイルの中身といっしょに送られてしまいます。
 header出力は一度しか出来ないのでしょうか、マルチパートにしたい時はどうすれば
よいのでしょうか?
(以上 )
« 最終編集者 YON 日時 2008 年 6 月 19 日(木) 10:34. »
会員
登録者: 6 2008
返信数: 5
:? 以下の方法を思いつきました。難しいかも知れませんが。
①予めダウンロードさせるPHP(download.php)を別に作っておく。
②呼び出されたPHPは、自身のHTML出力が終った後、
function calldownload(){
 $host = $_SERVER['HTTP_HOST'];
 $uri = rtrim(dirname($_SERVER['PHP_SELF']), '/\\');
 $extra = 'download.php';
 header("Location: http://$host$uri/$extra";);
 exit;
}
を呼び出して、download.phpに遷移するようにする。
です。この時、「ダウンロードさせるファイル名をどうやって引き渡せばよいか」
ですが、クッキーとか、セッションとかを使えば出来そうな気がします。
それとも、呼びだすURLの後ろに、
 $extra = 'download.php?file=filename';
と付けて、download.phpで単純に受取れるかもしれません。
« 最終編集者 YON 日時 2008 年 6 月 19 日(木) 11:19. »
会員
登録者: 9 2007
返信数: 9
通常はmailの話だけど
http://www.google.co.jp/search?q=mime%20multi&hl=ja&lr=lang_ja
試してないから判らないけどこれでできたりしないかな?
会員
登録者: 10 2007
返信数: 71
こんにちは。

少し気がついたのですが、PHPマニュアルに
引用
覚えておいて頂きたいのは、header() 関数は、 通常の HTML タグまたは PHP からの出力にかかわらず、すべての実際の 出力の前にコールする必要があることです。

となっていますので、その方法だとエラーになるかと思います。

そこで、Javascriptを使う方法はいかがでしょうか?。呼び出されたPHPが出力するHTMLの中に、「ページが表示された時にdownload.phpを呼び出すJavascript」を入れておくのです。
ファイル名の受け渡しはセッションを使うのが手っ取り早いかもしれません。
会員
登録者: 6 2008
返信数: 5
:) ヒントをいただき、ありがとうございました。やはりheader("Location: を使うやり方はだめでした。
そこでkona@mさん提案のJavascriptと併用する方法で、特にセッションもクッキーも使わずに出来ました。
以下のようにやりました。(ご参考までに)
(最初にリクエストを投げるhtmlのフォーム:yygeocodingm.htm)
<form name="upform" id="upform" action="http://yoneyone.my-sv.net/php/geocodingm.php"
method="post" enctype="multipart/form-data" >

Geocoding サービスの選択
<select name="service[]" id="service" />
<option value="google" />google
<option value="yahoo" />yahoo
</select><br><br>
住所ファイルの選択
<input type="file" name="upfilename" id="upfilename" />
<input type="submit" name="submitbotton" id="submitbotton" value="送信" /><br>
<input type="reset" name="reset" value="クリア" />
</form>

(処理するPHP:geocodingm.php)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<meta http-equiv="content-type" content="text/html; charset=EUC-JP"/>
<META http-equiv="Cache-Control" content="no-cache">
<META http-equiv="Expires" content="0">
<title>YY GeoCoding 結果</title>
<script type="text/javascript">
//<![CDATA[
function back(){
location.href="http://yoneyone.my-sv.net/yygeocodingm.htm";
}
function closing(filename){
location.href="http://yoneyone.my-sv.net/php/yygoddel.php?fname=" + filename;
}
function download(filename){
location.href="http://yoneyone.my-sv.net/php/yygodown.php?fname=" + filename;
}

//]]>
</script>
<?php
if (!empty($_FILES['upfilename']["name"])){
$service=$_POST['service'][0];
if (is_uploaded_file($_FILES['upfilename']['tmp_name'])){
$fname = "../temp/" . $_FILES['upfilename']["name"];
print "<body onunload=\"closing('$fname')\">";
$fin = fopen($_FILES['upfilename']['tmp_name'],"rb");

   処理本体(省略)

print "<hr><br><b>";
print " $service で $count 件の住所の検索が完了しました。<br><br>";
print "処理時間は $syori_jikan 秒でした。<br><br>";
print "<form action=# name='downform' id='downfom'>";
print "<input type='button' name='backbtn1'
value='検索結果ファイルの受信' onClick='download(\"$fname\")'>";
print "<input type='button' name='backbtn2'
value='終了' onClick='closing(\"$fname\")' />";
print "</form>";

print "<hr></b>";
print "<font color=#ff1493><b>※(注意:FireFox等のタブブラウザーでご利用の方へ)</font></b><br>";
print "<font color=#008b8b><b>!</b>ダウンロードを行なわないで終了する場合、終了ボタンで終了してください。";
print "ブラウザーの戻るボタンで終了すると、ごみが残ります。</font><br>";
}
}else{
print "<body>";
print "送信ファイルを選択して下さい。<br><br>";
print "<form>";
print "<input type='button' name='backbtn1' value='戻る' onClick='back()' />";
print "</form>"
;
}
?>
</body>
</html>

(ダウンロードさせるPHP:yygodown.php)
<?php
$fname = "{$_REQUEST['fname']}";
$faray =explode("/",$fname);
$downname = $faray[count($faray)-1];
header("Content-Disposition: attachment; filename=$downname");
header("Content-Type: application/x-csv");
header('Content-Length:'. filesize($fname));

readfile($fname);
unlink($fname);
?>

(取り消しのPHP:yygoddel.php)
<?php
$fname = "{$_REQUEST['fname']}";
if(file_exists($fname)){
unlink($fname);
}
header("Location: http://yoneyone.my-sv.net/yygeocodingm.htm";);
?>


で、一応期待どうりにできました。
http://yoneyone.my-sv.net/yygeocodingm.htm で試してみてください。
:( 問題が少々あります。
PHPが原因ではないのかもしれませんが、FireFoxのブラウザーの戻るのボタンでPHP
で出力したページから戻る時、<body>タグで指定したJavascriptのonunload=xxx('')の関数が動きません。IE(6.0)ではブラウザーの戻るボタンでonunloadイベントが
ちゃんと検出されているのですが....。他のブラウザーは試していません。
(以上)
会員
登録者: 10 2007
返信数: 71
とりあえず本来の目的が達成できたようで良かったですね。

(すみません、これよりPHPの話からはそれてしまうかもしれません。>他の皆様)

で、Firefoxでの動作についてですが、この投稿に書かれていたgeocodingm.phpの出力部分をコピーペーストしてローカルなテスト環境を作ってみました。「location.href=」の部分をalert()に置き換えて、Firefox3にて表示・ページ移動させてみたところ、onunloadイベント自体は発動しているように見えます。
function back(){
alert("http://yoneyone.my-sv.net/yygeocodingm.htm");
}
function closing(filename){
alert("http://yoneyone.my-sv.net/php/yygoddel.php?fname=" + filename);
}
function download(filename){
alert("http://yoneyone.my-sv.net/php/yygodown.php?fname=" + filename);
}
(こんな感じに変えてみました)
Firefox2はもう消してしまったのでわかりませんが・・・。

あとPHPでアップロードファイルから処理して別のファイルを返すというと、アップロードの受信・ファイル出力・ゴミファイルの削除が一度のリクエストで処理できるようになればいいのかもしれませんが、ちょっと今は実現できるかどうかわかりません。もしそれが出来れば根本的な解決が出来るのでは?と思ってみたりしますが、どうでしょうか。

それと、SAYKAさんのアイデアも面白そうですね。「サーバープッシュ」で検索するとより近いかもしれません。

p.s.初めてonunloadイベントを使ってみました。今までピンと来ていなかったのですが、試してみたら何か使えそうな気がしてきました。ありがとうございました。
会員
登録者: 6 2008
返信数: 5
<PHPの話からはそれているので、あまり深堀りしませんが>

:? Firefoxでは、location.hrefの使い方に制限があるようです。
FirefoxでもonUnloadイベントで呼ばれる関数は、ちゃんと実行されていました。
alert()で確認出来ました。しかし、location.href=xxxで代入した場合、
URIの?以降がセットされないようです。
location.sarch とか、location.reload とかいろいろ試しましたが、
onUnloadイベントで呼ばれた場合はだめなようです。
location.hrefはIEとかなり動作が違うみたいで、
http://blog.gpso.info/javascript_ajax/
にも、PHPとのシームレス通信について、参考になりそうな例がありましたが、
これ以上複雑にしても苦しいので、戻るボタンでphpを呼び出すのはあきらめます。
どうもありがとうございました。
« 最終編集者 YON 日時 2008 年 6 月 24 日(火) 17:49. »
会員
登録者: 6 2008
返信数: 5
:) 追記
サーバプッシュとかクライアントプルとか概念は何となく解るのですが、自分で実装するとなると
いろいろな知識が必要で、素人にはとっても難しそうです。
せいぜい、簡単なAJAXなページを作るぐらいです。
今回のページも、Javascriptを主体に、ファイルI/O部分、クロスドメインアクセス部分のみPHPのCGIにする事も出来たのですが、PHP学習のため、PHPを主体に作ろうと思ったので、苦労する事になりました。一方、文字コードのハンドリングや、ファイルI/O等、PHPだからこそ楽に作れた部分もありました。
(以上)

ページ: 1

日本PHPユーザ会 掲示板 » PHP事はじめ » HTMLの送信とファイルのダウンロードを同時にするにはどうするのですか

日本PHPユーザ会 掲示板 は UseBB 1 フォーラムソフトウェア を使用しています